sdOnPowerOff EQU 1 ;call procedure before power off
sdOnRestart EQU 2 ;call procedure before restart
sdOnUnmount EQU 4 ;call procedure before unmounting
sdOnDrivers EQU 8 ;call procedure before closing drivers
sdRestartOrPower EQU sdOnPowerOff + sdOnRestart
; Routine selectors
; (Note: You can invoke each of the Shutdown Manager routines with
; a macro that has the same name as the routine preceded by an
; underscore.)
sdPowerOff .EQU 1
sdRestart .EQU 2
sdInstall .EQU 3
sdRemove .EQU 4
Trap Macro Name
_Shutdown
(Note: You can invoke each of the Shutdown Manager routines with a macro that has the same name as the routine preceded by an underscore. Also, be aware that the _Shutdown macro is not in ROM.)
\,175
175
Interface for Sound Manager
CONST { Command numbers for SndDoCommand }
nullCmd = 0;
initCmd = 1;
freeCmd = 2;
quietCmd = 3;
flushCmd = 4;
waitCmd = 10;
pauseCmd = 11;
resumeCmd = 12;
callBackCmd = 13;
syncCmd = 14;
emptyCmd = 15;
tickleCmd = 20;
requestNextCmd = 21;
howOftenCmd = 22;
wakeUpCmd = 23;
availableCmd = 24;
noteCmd = 40;
restCmd = 41;
freqCmd = 42;
ampCmd = 43;
timbreCmd = 44;
waveTableCmd = 60;
phaseCmd = 61;
soundCmd = 80;
bufferCmd = 81;
rateCmd = 82;
midiDataCmd = 100;
{ Synthesizer numbers for SndNewChannel }
noteSynth = 1; {note synthesizer}
waveTableSynth = 3; {wave table synthesizer}
sampledSynth = 5; {sampled sound synthesizer}
MIDISynthIn = 7; {MIDI synthesizer in}
MIDISynthOut = 9; {MIDI synthesizer out}
{ Param2 values }
MidiInitChannel = n; {MIDI Channel to init $0 .. $F}
MidiInitChanFilter = $10; {set to initialize a MIDI Channel}
MidiInitRawMode = $100; {set to send raw MIDI data}
{ Queue length }
StdQLength = 128 {standard queue length}
Data Types
TYPE SndCommand = PACKED RECORD
cmd: INTEGER; {command number}
param1: INTEGER; {first parameter}
param2: LONGINT; {second parameter}
END;
Time = LONGINT;
SndChannel = RECORD
nextChan: SndChannelPtr; {pointer to next channel}
firstMod: ModifierStubPtr; {pointer to first modifier}
callBack: ProcPtr; {pointer to channel's call back
procedure}
userInfo: LONGINT; {free for use}
wait: Time; {used internally}
cmdInProg: SndCommand; {used internally}
flags: INTEGER; {used internally}
qLength: INTEGER; {queue length}
qHead: INTEGER; {used internally}
qTail: INTEGER; {used internally}
queue: ARRAY[0..stdQLength-1] OF SndCommand
END;
ModifierStub = RECORD
nextStub: ModifierStubPtr; {pointer to next modifier}
code: ProcPtr; {pointer to modifier code}
userInfo: LONGINT; {free for modifier to use}
count: Time; {used internally}
every: Time; {used internally}
flags: SignedByte; {used internally}
hState: SignedByte {used internally}
END;
Result Codes
Name Value Meaning
badChannel –205 Invalid channel queue length
badFormat –206 Handle to 'snd ' resource was invalid
noHardware –200 No hardware support for the specified synthesizer
notEnoughHardware –201 No more channels for the specified synthesizer
queueFull –203 No room in the queue
resProblem –204 Problem loading the resource
\,176
176
Interface for Start Manager
TYPE DefStartType = (slotDev,scsiDev);
DefStartPtr = ^DefStartRec
DefStartRec = RECORD
CASE DefStartType OF
slotDev:
sdExtDevID: SignedByte; {external device ID}
sdPartition: SignedByte; {reserved}
sdSlotNum: SignedByte; {slot number}
sdSRsrcID: SignedByte; {SResourceID}
scsiDev:
sdReserved1: SignedByte; {reserved}
sdReserved2: SignedByte; {reserved}
sdRefNum: INTEGER {driver reference number}
END;
DefVideoPtr = ^DefVideoRec
DefVideoRec = RECORD
sdSlot: SignedByte; {slot number}
sdSResource: SignedByte; {sResourceID}
END;
DefOSPtr = ^DefOSRec
DefOSRec = RECORD
sdReserved: SignedByte; {reserved--should be 0}
sdOSType: SignedByte; {operating system type}
END;
Assembly-Language Information
Structure of Default Startup Device Parameter Block (Slot)
sdExtDevID External device ID (byte)
sdPartition Reserved—should be 0 (byte)
sdSlotNum Slot number (byte)
sdSRsrcID SResource ID (byte)
Structure of Default Startup Device Parameter Block (SCSI)
sdReserved1 Reserved—should be 0 (byte)
sdReserved2 Reserved—should be 0 (byte
sdRefNum Driver reference number (word)
Structure of Default Video Device Parameter Block
sdSlot Slot number (byte)
sdSResource SResource ID (byte)
Structure of Default OS Parameter Block
sdReserved Reserved—should be 0 (byte)
sdOSType Operating system type (byte)
Variables
CPUFlag Microprocessor in use (word)
TimeDBRA Number of times the DBRA instruction can be executed per millisecond (word)
TimeSCCDB Number of times the SCC can be accessed per millisecond (word)
TimeSCSIDB Number of times the SCSI can be accessed per millisecond (word)
\,177
177
Interface for Deferred Task Manager
TYPE
DeferredTask = RECORD
qLink: QElemPtr; {next queue entry}
qType: INTEGER; {queue type}
dtFlags: INTEGER; {reserved}
dtAddr: ProcPtr; {pointer to task}
dtParm: LONGINT; {optional parameter}
dtReserved: LONGINT {reserved--should be 0}
END;
Assembly-Language Information
Structure of Deferred Task Manager Queue Entry
qLink Pointer to next queue entry
qType Queue type (word)
dtFlags Reserved (word)
dtAddr Address of task
dtParm Optional parameter (long)
dtResrvd Reserved—should be 0 (long)
dtQElSize Size in bytes of queue element
Variables
DTQueue Deferred task queue header (10 bytes)
JDTInstall Jump vector for DTInstall routine
\,166
166
Interface for MPW Performance routines
TYPE
PLongs = ^ALongs;
ALongs = ARRAY [1..8000] OF LONGINT;
PInts = ^AInts;
HInts = ^PInts;
AInts = ARRAY [1..8000] OF INTEGER;
{ PerfGlobals are declared as a record, so main program can allocate
as globals, desk accessory can add to globals allocated via pointer,
print driver can allocate via low memory, etc. }
TP2PerfGlobals = ^TPerfGlobals;
TPerfGlobals = RECORD
startROM: LONGINT; {ROM Base}
romHits: LONGINT; {used if MeasureROM is false}
misses: LONGINT; {count of PC values outside measured memory}
segArray: PLongs; {array of segment handles}
sizeArray: PLongs; {array of segment sizes}
idArray: HInts; {array of segment rsrc IDs}
baseArray: PLongs; {array of offsets to counters for each segment}
samples: PLongs; {samples buffer}
buffSize: LONGINT; {size of samples buffer in bytes}
timeInterval: INTEGER; {number of clock intervals between interrupts}
bucketSize: INTEGER; {size of buckets power of 2}
log2buckSize: INTEGER; {used in CvtPC}
pcOffset: INTEGER; {offset to the user PC at interrupt time.}
numMeasure: INTEGER; {# Code segments (w/o jump table)- ROM etc.}
firstCode: INTEGER; {index of first Code segment}
takingSamples: BOOLEAN; {true if sampling is enabled}
measureROM: BOOLEAN;
measureCode: BOOLEAN;
ramSeg: INTEGER; {index of "segment" record to cover RAM > 0 if RAM (misses) are to be bucketed.}
ramBase: LONGINT; {beginning of RAM being measured.}
measureRAMbucketSize: INTEGER;
measureRAMlog2buckSize: INTEGER;
romVersion: INTEGER;
vRefNum: INTEGER; {Volume where the report file is to be created}
volumeSelected: BOOLEAN; {True if user selects the report file name}
rptFileName: Str255; {Report file name}
rptFileCreator: Str255; {Report File Creator}
rptFileType: Str255; {Report File type}
getResType: ResType; {Resource type}
END;
\ ,178
178
Interface information for writing HC 2.0 XCMDS
External windows are an extension of external commands (XCMDs and XFCNs). Two new callbacks, NewXWindow and GetNewXWindow, cause HyperCard to create a new window and save with it a reference to the XCMD that made the call. Then, whenever HyperCard receives an event from the Toolbox Event Manager which belongs to the window, it calls the XCMD that created the window with arguments that allow it to handle the event. Otherwise, HyperCard handles the event itself.
Whenever an XCMD is called by HyperCard, it receives a pointer to an XCMDBlock, just as it did in earlier versions of HyperCard.
XCmdPtr = ^XCmdBlock;
XCmdBlock = RECORD
paramCount: INTEGER;
params: ARRAY[1..16] OF Handle;
returnValue: Handle;
passFlag: BOOLEAN;
entryPoint: ProcPtr; { to call back to HyperCard }
request: INTEGER;
result: INTEGER;
inArgs: ARRAY[1..8] OF LongInt;
outArgs: ARRAY[1..4] OF LongInt;
END;
When HyperCard calls an XCMD to handle an event for an external window, some of the fields of the XCMDBlock have a new meaning. The paramCount field is set to -1, indicating that the XCMD has been called to handle an event. The first parameter, params[1], is a pointer to an XWEventInfo block, defined as follows.
XWEventInfoPtr = ^XWEventInfo;
XWEventInfo = RECORD
event: EventRecord;
eventWindow: WindowPtr;
eventParams: ARRAY[1..9] OF LongInt;
eventResult: Handle;
END;
\ InitResources
1
Function InitResources : INTEGER;
InitResources is called by the system whcn it starts up, and should
not be called by the application. It initializes the Resource Manager,
opens the system resource file, reads the resource map from the file
into memory, and returns a reference number for the file.
(note)
The application doesn't need the reference number for the
system resource file, because every Resource Manager
routine that has a reference number as a parameter
interprets Ø to mean the system resource file.
\ RsrcZoneInit
1
Procedure RsrcZoneInit;
RsrcZoneInit is called automatically when your application starts
up, to initialize the resource map read from the system resource file;
normally you'll have no need to call it directly. It "cleans up" after
any resource access that may have been done by a previous application.
First it closes all open resource files except the system resource
file. Then, for every system resource that was read into the
application heap (that is, whose resSysHeap attribute is Ø), it
replaces the handle to that resource in the resource map with NIL.
This lets the Resource Manager know that the resource will have to be
read in again (since the previous application heap is no longer
around).
\ CreateResFile
1
Procedure CreateResFile (fileName: Str255);
CreateResFile creates a resource file containing no resource data or
copy of the file's directory entry. If there's no file at all with the
given name, it also creates an empty data fork for the file. If
there's already a resource file with the given name (that is, a
resource form that isn't empty), CreateResFile will do nothing and the
ResError function will return an appropriate Operating System result
code.
(note)
Before you can work with the resource file, you need to
open it with OpenResFile.
\ OpenResFile
1
Function OpenResFile (fileName: Str255) : INTEGER;
OpenResFile opens the resource file having the given name and makes
it the current resource file. It reads the resource map from the file
into memory and returns a reference number for the file. It also reads
in every resource whose resPreload attribute is set. If the resource
file is already open, it doesn't make it the current resource file; it
simply returns the reference number.
(note)
You don't have to call OpenResFile to open the system
Resource file or the application's resource file, because
they're opened when the system and the application start
up, respectively. To get the reference number of the
application's resource file, you can call CurResFile
after the application starts up (before you open any
other resource file).
If the file can't be opened, OpenResÏile will return -1 and the
ResError function will return an appropriate Operating System result
code. For example, an error occurs if there's no resource file with
the given name.
\ CloseResFile
1
Procedure CloseResFile (refNum: INTEGER);
Given the reference number of a resource file, CloseResFile does the
following:
- updates the resource file by calling the UpdateResFile procedure
- for each resource in the resource file, releases the memory it
occupies by calling the ReleaseResource procedure
- releases the memory occupied by the resource map
- closes the resource file
If there's no resource file open with the given reference number,
CloseResFile will do nothing and the ResError function will return the
result code resFNotFound. A refNum of Ø represents the system resource
file, but if you ask to close this file, CloseResFile first closes all
other open resource files.
A CloseResFile of every open resource file except the system
resource file is done automatically when the application terminates. So
you only need to call CloseResFile if you want to close the system
resource file, or if you want to close any resource file before the
application terminates.
\ ResError
1
Function ResError : INTEGER;
Called after one of the various Resource Manager routines that may
result in an error condition, ResError returns a result code
identifying the error, if any. If no error occurred, it returns the
result code
CONST noErr = Ø; {no error}
If an error occurred at the Operating System level, it returns an
Operating System result code, such as the File Manager "disk I/O" error
or the Memory Manager "out of memory" error. (See the File Manager and
Memory Manager manuals for a list of the result codes.) If an error
happened at the Resource Manager level, ResError returns one of the
following result codes:
CONST resNotFound = -192; {resource not found}
resFNotFound = -193; {resouce file not found}
addResFailed = -194; {AddResource failed}
rmvResFailed = -196; {RmveResource failed}
Each routine description tells which errors may occur for that
routine. You can also check for an error after system startup, which
calls InitResources, and application startup, which opens the
application's resource file.
\ CurResFile
1
Function CurResFile : INTEGER;
CurResFile returns the reference number of the current resource file
You can call it when the application starts up to get the reference
number of its resource file.
(note)
If the system resource file is the current resource file,
CurResFile returns the actual reference number of the
system reference file (found in the global variable
SysMap). You needn't worry about this number being used
(instead of Ø in the routines that require a reference
number; these routines recognize both Ø and the actual
reference number as referring to the system resource
file.
\ HomeResFile
1
Function HomeResFile (theResource: Handle) : INTEGER;
Given a handle to a resource, HomeResFile returns the reference
number of the resource file containing that resource. If the given
handle isn't a handle to a resource, HomeResFile will return -1 and the
ResError function will return the result code resNotFound.
\ UseResFile
1
Procedure UseResFile (refNum: INTEGER);
Given the reference number of a resource file, UseResFile sets the
current resource file to that file. If there's no resource file open
with the given reference number, UseResFile will do nothing and the
ResError function will return the result code resFNotFound. A refNum
of Ø represents the system resource file.
Open resource files are arranged as a linked list; the most recently
opened file is at the end of the list and is the first one to be
searched. UseResFile lets you start the search with a file opened
earlier; the file(s) following it on the list ate then left out of the
search process. This is best understood with an example. Assume there
are four open resource files (RØ through R3); the search order is R3,
R2, R1, RØ. If you call UseResFile(R2), the search order becomes R2,
R1, RØ; R3 is no longer searched. If you then open a fifth resource
file (R4), it's added to the end of the list and the search order
becomes R4, R3, R2, R1, RØ.
This procedure is useful if you no longer want to override a system
resource with one by the same name in your application's resource file.
You can call UseResFile(Ø) to leave the application resource file out
of the search, causing only the system resource file to be searched.
(warning)
Early versions of some desk accessories may, upon
closing, always set the current resource file to the one
opened just prior to the accessory, ignoring any
additional resource files that may have been opened while
the accessory was in use. To be safe, whenever desk
accessories may have been in use, call UseResFile to
ensure access to resource files opened after accessories.
\ CountTypes
1
Function CountTypes : INTEGER;
CountTypes returns the number of resource types in all open resource
NewDialog creates a dialog as specified by its parameters and
returns a pointer to the new dialog. The first eight parameters
(dStorage through refCon) are pased to the Window Manager function
NewWindow, which creates the dialog window; the meanings of these
parameters are summarized below. The items parameter is a handle to the
dialog's item list. You can get the items handle by calling the
Resource Mangager to read the item list from the resource file into
memory (But make a DetachResource before!).
(note)
Advanced programmers can create their own item lists in
memory rather than have them read from a resource file.
The exact format is given later under "Formats of
Resources for Dialogs and Alerts".
DStorage is analogous to the wStorage parameter of NewWindow; it's a
pointer to the storage to use for the dialog record. If you pass NIL
for dStorage, the dialog record will be allocated on the heap (which,
in the case of modeless dialogs, may cause the heap to become
fragmented).
BoundsRect, a rectangle given in global coordinates, determines the
dialog window's size and location. It becomes the portRect of the
window's grafPort. Remember that the top coordinate of this rectangle
should be at least 25 points below the top of the screen for a modal
dialog, to allow for the menu bar and the border around the portRect,
and at least 40 points below the top of the screen for a modeless
dialog, to allow for the menu bar and the window's title bar.
Title is the title of a modeless dialog box; pass the empty string
for modal dialogs.
If the visible parameter is TRUE, the dialog window is drawn on the
screen. If it's FALSE, the window is initially invisible and may later
be shown with a call to the Window Manager procedure ShowWindow.
(note)
NewDialog generates an update event for the entire window
contents, so the items aren't drawn immediately, with the
exception of controls. The Dialog Manager calls the
Control Manager to draw controls, and the Control Manager
draws them immediately rather than via the standard
update mechanism. Because of this, the Dialog Manager
calls the Window Manager procedure ValidRect for the
enclosing rectangle of each control, so the controls
won't be drawn twice. If you find that the other items
aren't being drawn soon enough after the controls, try
making the window invisible initially and then calling
ShowWindow to show it.
ProcID is the window definition ID, which leads to the window
definition function for this type of window. The window definition IDs
for the standard types of dialog window are dBoxProc for the modal type
and documentProc for the modeless type.
The behind parameter specifies the window behind which the dialog
window is to be placed on the desktop. Pass POINTER(-1) to bring up
the dialog window in front of all other windows.
GoAwayFlag applies to modeles dialog boxes; if it's TRUE, the dialog
window has a close box in its title bar when the window is active.
RefCon is the dialog window's reference value, which the application
may store into and access for any purpose.
NewDialog sets the font of the dialog window's grafPort to the
system font or, if you previously called SetDAFont, to the specified
font. It also sets the window class in the window record to dialogKind.
\ GetNewDialog
9
Function GetNewDialog (dialogID: INTEGER; dStorage: Ptr; behind:
WindowPtr) : DialogPtr;
Like NewDialog (above), GetNewDialog creates a dialog as specified
by its parameters and returns a pointer to the new dialog. Instead of
having the parameters boundsRect, title, visible, procID, goAwayFlag,
and refCon, GetNewDialog has a single dialogID parameter, where
dialogID is the resource ID of a dialog template that supplies the same
information as those parameters. The dialog template also contains the
resource ID of the dialog's item list. After calling the Resource
Manager to read the item list into memory (if it's not already in
memory), GetNewDialog makes a copy of the item list and uses that copy;
thus you may have multiple independent dialogs whose items have the
same types, locations, and initial contents. The dStorage and behind
parameters of GetNewDialog have the same meaning as in NewDialog.
The GetNewDialog routine will attempt to load a 'dctb' resource and returns a pointer to a color grafPort if the resource exists. If no 'dctb' resource is present, GetNewDialog returns a pointer to an old grafPort.
The dialog color table is copied before it is passed to SetWinSize unless its ctSize field is equal to –1, indicating that the default window colors are to be used instead. The copy is made so that the color table resource can be purged without affecting the dialog.
The color dialog item list resource is duplicated as well, so it can be purgeable.
\ CloseDialog
9
Procedure CloseDialog (theDialog: DialogPtr);
CloseDialog removes theDialog's window from the screen and deletes
it from the window list, just as when the Window Manager procedure
CloseWindow is called. It releases the memory occupied by the
following:
-The data structures associated with the dialog window (such as the
window's structure, content, and update regions).
-All the items in the dialog (except for pictures and icons, which
might be shared resources), and any data structures associated
with them. For example, it would dispose of the region occupied
by the thumb of a scroll bar, or a similar region for some other
control in the dialog.
CloseDialog does not dispose of the dialog record or the item list.
Figure 6 illustrates the effect of CloseDialog (and DisposDialog,
described below).
Call CloseDialog when you're done with a dialog if you supplied
NewDialog or GetNewDialog with a pointer to the dialog storage (in the
dStorage parameter) when you created the dialog.
(note)
Even if you didn't supply a pointer to the dialog
storage, you may want to call CloseDialog if you created
the dialog with NewDialog. You would call CloseDialog if
you wanted to keep the item list around (since, unlike
GetNewDialog, NewDialog does not use a copy of the item
list).
\ DisposDialog
9
Procedure DisposDialog (theDialog: DialogPtr);
DisposDialog calls CloseDialog (above) and then releases the memory
occupied by the dialog's item list and dialog record. Call
DisposDialog when you're done with a dialog if you let the dialog
record be allocated on the heap when you created the dialog (by passing
NIL as the dStorage parameter to NewDialog or GetNewDialog).
\ CouldDialog
9
Procedure CouldDialog (dialogID: INTEGER);
CouldDialog ensures that the dialog template having the given
resource ID is in memory and makes it unable to be purged. It does the
same for the dialog window's definition function, the dialog's item list
resource, and any item defined as resources. This is useful if the
dialog box may come up when the resource file isn't accessible, such as
during a disk copy.
The CouldDialog procedure makes the dialog color table template unpurgeable (reading it into memory if it isn’t already there), if it exists. It does the same for the dialog’s color item list, if it has one.
Warning: CouldDialog doesn’t load or make 'FONT' or 'FOND' resources indicated in the color item list unpurgeable.
\ FreeDialog
9
Procedure FreeDialog (dialogID: INTEGER);
Given the resource ID of a dialog template previously specified in a
call to CouldDialog (above), FreeDialog undoes the effect of
CouldDialog. It should be called when there's no longer a need to keep
the resources in memory.
Given the resource ID of a dialog template previously specified in a call to CouldDialog, the FreeDialog routine undoes the effect of CouldDialog, by restoring the original purge state of the color table and color item list resources.
\ ModalDialog
9
Procedure ModalDialog (filterProc: ProcPtr; VAR itemHit: INTEGER);
Call ModalDialog after creating a modal dialog and bringing up its
window in the frontmost plane. ModalDialog repeatedly gets and handles
events in the dialog's window; after handling an event involving an
enabled dialog item, it returns with the item number in itemHit.
Normally you'll then do whatever is appropriate as a response to an
event in that item.
ModalDialog gets each event by calling the Toolbox Event Manager
Function GetNextEvent. If the event is a mouse-down event outside the
content region of the dialog window, ModalDialog emits sound number 1
(which should be a single beep) and gets the next event; otherwise, it
filters and handles the event as described below.
(note)
Once before getting each event, ModalDialog calls
SystemTask, a Desk Manager procedure that needs to be
called regularly if the application is to support the use
of desk accessories.
The filterProc parameter determines how events are filtered. If it's
NIL, the standard filterProc function is executed; this causes
ModalDialog to return 1 in itemHit if the Return key or Enter key is
pressed. If filterProc isn't NIL, ModalDialog filters events by
executing the function it points to. Your filterProc function should
have three parameters and return a Boolean value. For example, this is
how it would be declared if it were named MyFilter:
FUNCTION MyFilter (theDialog: DialogPtr; VAR theEvent:
EventRecord; VAR itemHit: INTEGER ) : BOOLEAN;
A function result of FALSE tells ModalDialog to go ahead and handle
the event, which either can be sent through unchanged or can be changed
to simulate a different event. A function result of TRUE tells
ModalDialog to return imediately rather than handle the event; in this
case, the filterProc function sets itemHit to the item number that
ModalDialog should return.
(note)
ModalDialog calls GetNextEvent with a mask that excludes
disk-inserted events. To receive disk-inserted events,
your filterProc function can call GetNextEvent (or
EventAvail) with a mask that accepts only that type of event.
ModalDialog handles the evnets for which the filterProc function
returns FALSE as follows:
-In response to an activate or update event for the dialog window,
ModalDialog activates or updates the window.
-If the mouse button is pressed in an editText item, ModalDialog
responds to the mouse activity as appropriate (displaying an
insertion point or selecting text). If a key-down event occurs
and there's an editText item, text entry and editing are handled
in the standard way for such items (except that if the Command key
is down, ModalDialog responds as though it isn't). In either
case, ModalDialog returns if the editText item is enabled or does
nothing if it's disabled. If a key-down event occurs when there's
no editText item, ModalDialog does nothing.
-If the mouse button is pressed in a control, ModalDialog calls the
Control Manager function TrackControl. If the mouse button is
released inside the control and the control is enabled,
ModalDialog returns; otherwise, it does nothing.
-If the mouse button is pressed in any other enabled item in the
dialog box, ModalDialog returns. If the mouse button is pressed
in any other disabled item or in no item, or if any other event
occurs, ModalDialog does nothing.
\ IsDialogEvent
9
Function IsDialogEvent (theEvent: EventRecord) : BOOLEAN;
If your application includes any modeless dialogs, call
IsDialogEvent after calling the Toolbox Event Manager function
GetNextEvent. Pass the current event in theEvent. IsDialogEvent
determines whether theEvent needs to be handled as part of a dialog. If
theEvent is an activate or update event for a dialog window, a
mouse-down event in the content region of an active dialog window, or
any other type of event when a dialog window is active, IsDialogEvent
returns TRUE; otherwise, it returns FALSE.
When FALSE is returned, just handle the event yourself like any
other event that's not dialog-related. When TRUE is returned, you'll
generally end up passing the event to DialogSelect for it to handle (as
described below), but first you should do some additional checking:
- DialogSelect doesn't handle keyboard equivalents for commands.
Check whether the event is a key-down event with the Command key
held down and, if so, carry out the command if it's one that
applies when a dialog window is active. (If the command doesn't
so apply, do nothing.)
- In special cases, you may want to bypass DialogSelect or do some
preprocessing before calling it. If so, check for those events
and respond accordingly. You would need to do this, for example,
if the dialog is to respond to disk-inserted events.
For cases other than these, pass the event to DialogSelect for it to
handle.
\ DialogSelect
9
Function DialogSelect (theEvent: EventRecord; VAR theDialog: DialogPtr;
VAR itemHit: INTEGER) : BOOLEAN;
You'll normally call DialogSelect after IsDialogEvent, passing in
theEvent an event that needs to be handled as part of a modeless
dialog. DialogSelect handles the event as described below. If the
event involves an enabled dialog item, DialogSelect returns a function
result of TRUE with the dialog pointer in theDialog and the item number
in itemHit; otherwise, it returns FALSE with theeDialog and itemHit
undefined. Normally when DialogSelect returns TRUE, you'll do whatever
is appropriate as a response to the event, and when it returns FALSE
you'll do nothing.
If the event is an activate or update event for a dialog window,
DialogSelect activates or updates the window ane returns FALSE.
If the event is a mouse-down event in an editText item, DialogSelect
responds as appropriate (displaying an insertion point or selecting
text). If it's a key-down event and there's an editText item, text
entry and editing are handled in the standard way. In either case,
DialogSelect returns TRUE if the editText item is enabled or FALSE if
it's disabled. If a key-down event is passed when there's no editText
item, DialogSelect returns FALSE.
(note)
For a key-down event, DialogSelect doesn't check to see
whether the Command key is held down; to handle keyboard
equivalents of commands, you have to check for them
before calling DialogSelect. Similarly, to treat a typed
character in a special way (such as ignore it, or make it
have the same effect as another character or as clicking
a button), you need to check for a key-down event with
that character before calling DialogSelect.
If the event is a mouse-down event in a control, DialogSelect calls
the Control Manager function TrackControl. If the mouse button is
released inside the control and the control is enabled, DialogSelect
returns TRUE; otherwise, it returns FALSE.
If the event is a mouse-down event in any other enabled item,
DialogSelect returns TRUE. If it's a mouse-down event in any other
disabled item or in no item, or if it's any other event, DialogSelect
DlgDelete is the same as DlgCut (above) except that it calls
TEDelete, for handling the Clear command.
\ DrawDialog
9
Procedure DrawDialog (theDialog: DialogPtr);
DrawDialog draws the contents of the given dialog box. Since
DialogSelect and ModallDialog handle dialog window updating, this
Procedure is useful only in unusual situations. You would call it, for
example, to display a dialog box that doesn't require any response but
merely tells the user what's going on during a time-consuming process.
\ Alert
9
Function Alert (alertID: INTEGER; filterProc: ProcPtr) : INTEGER;
This function invokes the alert defined by the alert template that
has the given resource ID. It calls the currnet sound procedure, if
any,l passing it the sound number specified in the alert template for
this stage of the alert. If no alert box is to be drawn at this stage,
Alert returns a function result of -1; otherwise, it creates and
displays the alert window for this alert and draws the alert box.
The Alert function looks for a resource of type 'actb' with the same ID as the alert. The alert color table is copied before it is passed to SetWinSize unless its ctSize field is equal to –1, indicating that the default window colors are to be used instead. The copy is made so that the color table resource can be purged without affecting the alert.
The color dialog item list resource is duplicated as well, so it can be purgeable.
(note)
It creates the alert window by calling NewDialog, and
does the rest of its processing by calling ModalDialog.
Alert repeatedly gets and handles events in the alert window until
an enabled item is clicked, at which time it returns the item number.
Normally you'll then do whatever is appropriate in response to a click
of that item.
Alert gets each event by calling theToolbox Event Manager function
GetNextEvent. If the event is a mouse-down event outside the content
region of the alert window, Alert emits sound number 1 (which should be
a single beep) and gets the next event; otherwise, it filters and
handles the event as describe below.
The filterProc parameter has the same meaning as in ModalDialog (see
above). If it's NIL, the standard filterProc function is executed,
which makes the Return key or the Enter key have the same effect as
clicking the default button. If you specify your own filterProc
Function and want to retain this feature, you must include it in your
Function. You can find out what the current default button is by
looking at the aDefItem field of the dialog record for the alert (via
the dialog pointer passed to the function).
Alert handles the events for which the filterProc function returns
FALSE as follows:
- If the mouse button is pressed in a control, Alert calls the
Control Manager procedure TrackControl. If the mouse buton is
released inside the control and the control is enabled, Alert
returns; otherwise, it does nothing.
- If the mouse button is pressed in any other enabled item, Alert
simply returns. If it's pressed in any other disabled item or in
no item, or if any other event occurs, Alert does nothing.
Before returning to the application with the item number, Alert
removes the alert box from the screen. (It disposes of the alert window
and its associated data structures, the item list, and the items.)
(note)
The Alert function's removal of the alert box would not
be the desired result if the user clicked a check box or
radio button; however, normally alerts contain only
static text, icons, pictures, and buttons that are
supposed to make the alert box go away. If your alert
contains other items besides these, consider whether it
might be more appropriate as a dialog.
\ StopAlert
9
Function StopAlert (alertID: INTEGER; filterProc: ProcPtr) : INTEGER;
StopAlert is the same as the Alert function (above) except that
before drawing the items of the alert in the alert box, it draws the
Stop icon in the top left corner of the box (within the rectangle
(10,20,42,52)). The Stop icon has the following resource ID:
CONST stopIcon = 0;
The call StopAlert look for a resource of type 'actb' with the same ID as the alert.
If the application's resource file doesn't include an icon with that
ID number, the Dialog Manager uses the standart Stop icon in the system
resource file (see Figure 7).
\ NoteAlert
9
Function NoteAlert (alertID: INTEGER; filterProcf: ProcPtr) : INTEGER;
NoteAlert is like StopAlert except that it draws the Note icon,
which has the following resource ID:
CONST noteIcon = 1;
The call NoteAlert look for a resource of type 'actb' with the same ID as the alert.
\ CautionAlert
9
Function CautionAlert (alertID: INTEGER; filterProc: ProcPtr) :
INTEGER;
CautionAlert is like StopAlert except that it draws the Caution
icon, which has the following resource ID:
CONST ctnIcon = 2;
The call CautionAlert look for a resource of type 'actb' with the same ID as the alert.
\ CouldAlert
9
Procedure CouldAlert (alertID: INTEGER);
CouldAlert ensures that the alert template having the given resource
ID is in memory and makes it unable to be purged. It does the same for
the alert window's definition function, the alert's item list resource,
and any items defined as resources. This is useful if the alert may
occur when the resource file isn't accessible, such as during a disk
copy.
The CouldAlert routine makes the alert color table template unpurgeable (reading it into memory if it isn’t already there), if it exists. It does the same for the alert’s color item list, if it has one.
Warning: Like CouldDialog, CouldAlert doesn’t load or make 'FONT' or 'FOND' resources indicated in the color item list unpurgeable.
\ FreeAlert
9
Procedure FreeAlert (alertID: INTEGER);
Given the resource ID of an alert template previously specified in a
call to CouldAlert (above), FreeAlert undoes the effect of CouldAlert.
It should be called when there's no longer a need to keep the resources
in memory.
Given the resource ID of an alert template previously specified in a call to CouldAlert, the FreeAlert routine undoes the effect of CouldAlert, by restoring the original purge state of the color table and color item list resources.
In the resource file having the reference number refNum, IUSetIntl
sets the international resource numbered theID (0 or 1) to the data
pointed to by tintlParam. The data may be either an existing resource
okr data that hasn't yet been written to a resource file. IUSetIntl
adds the resource to the specified file or replaces the resource if it's
already there.
\ IUCompString
13
Function IUCompString (aStr,bStr: Str255) : INTEGER; [Pascal only]
IUCompString compares aStr and bStr as described above under
"International String Comparison", taking both primary and secondary
ordering into consideration. It returns one of the values listed
below.
Result Meaning Example
aStr bStr
-1 aStr is less than bStr 'Ab' 'ab'
0 aStr equals bStr 'Ab' 'Ab'
1 aStr is greater than bStr 'Ac' 'ab'
\ IUMagString
13
Function IUMagString (aPtr,bPtr: Ptr; aLen,bLen: INTEGER) : INTEGER;
IUMagString is the same as IUCompString (above) except that instead
of comparing two Pascal strings, it compares the string defined by aPtr
and aLen to the string defined by bPtr and bLen. The pointer points to
the first character of the string (any byte in memory, not necesarily
word-aligned), and the length specifies the number of characters in the
string.
\ IUEqualString
13
Function IUEqualString (aStr,bStr: Str255) : INTEGER; [Pascal only]
IUEqualString comapares aStr and bStr for equality without regard
for secondary ordering, as described above under "international String
Comparison". If the strings are equal, it returns 0; otherwise, it
returns 1. For example, if the strings are 'Rose' and 'rose',
IUEqualString considers them equal and returns 0.
(note)
See also EqualString in the Operating System Utilities
manual *** doesn't yet exist***.
\ IUMagIDString
13
Function IUMagString (aPtr,bPtr: Ptr; aLen,bLen: INTEGER) : INTEGER;
IUMagIDString is the same as IUEqualString except that instead of comparing two Pascal strings, it compares the string defined by aPtr and aLen to the string defined by bPtr and bLen. The pointer points to the first character of the string (any byte in memory, not necessarily word-aligned), and the length specifies the number of4 characters in the string.
\ NumToString
13
Procedure NumToString (theNum: LongInt; VAR theStringd: Str255);
HSetState is used in conjunction with HGetState; it sets the byte
that contains the flags of the master pointer for the given handle
to the byte specified by flags.
\ UnloadSeg
15
Procedure UnloadSeg (routineAddr: Ptr);
UnloadSeg unloads a segment, making it relocatable and purgeable;
routineAddr is the address of any externally referenced routine in the
segment. The segment won't actually be purged until the memory it
occupies is needed. If the segment is purged, the Segment Loader will
reload it the next time one of the routines in it is called.
\ CountAppFiles
15
Procedure COuntAppFiles (VAR message: INTEGER; VAR count: INTEGER);
CountAppFiles deciphers the Finder information passed to your
application, and returns information about the documents that were
selected when your application was started up. It returns the number
of selected documents in the count parameter, and a number in the
message parameter that indicates whether the documents are to be opened
or printed:
CONST appOpen = 0; {open the document(s)}
appPrint = 1; {print the document(s)}
\ GetAppFiles
15
Procedure GetAppFiles (index: INTEGER; VAR theFile: AppFile);
GetAppFiles returns information about a document that was selected
when your application was started up (as listed in the Finder
information). The index parameter indicates the file for which
information should be returned; it must be between 1 and the number
returned by CountAppFiles, inclusive. The information is returned in
the following data structure:
TYPE AppFile = RECORD
vRefNum: INTEGER; {volume reference number}
fType: OSType; {file type}
versNum: INTEGER; {version number}
fName: Str255; {file name}
END;
Volume reference number, file type, version number, and file name
are discussed in the File Manager manual.
\ ClrAppFiles
15
Procedure ClrAppFiles (index: INTEGER);
ClrAppFiles changes the Finder information passed to your aplication
about the specified file such that the Finder knows you've processed
the file. The index parameter must be between 1 and the number
returned by CountAppFiles, inclusive. You should call ClrAppFiles for
every document your application opens or prints, so that the
information returned by CountAppFiles and GetAppFiles is always
correct. (ClrAppFiles sets the file type in the Finder information to
0.)
\ GetAppParms
15
Procedure GetAppParms (VAR apName: Str255; VAR apRefNum: INTEGER;
VAR apParam: Handle);
GetAppParms returns information about the current application. It
returns the application name in apName and the reference number for the
application's resource file in apRefNum. A handle to the Finder
information is returned in apParam, but the Finder information is more
easily accessed with the GetAppFiles call.
\ ExitToShell
15
Procedure ExitToShell;
ExitToShell provides an exit from an application by starting up the
Finder (after releasing the entire application heap).
\ Chain
15
Chain procedure
Trap Macro _Chain
On entry (A0): Pointer to application's file name.
4(A0): Configuration of sound and screen buffer (word).
Chain starts up an application without doing anything to the application Heap so the current application can let another application take over while still keeping its data around in the heap.
Chain also configures memory for the sound and screen buffer. The
value you pass in 4(A0) determines which sound and screen buffers are
allocated:
• if you pass 0 in 4(A0), yu get the main sound and screen buffers;
in this case, you have the largest amount of memory available to
your application.
• any positive value in 4(A0) causes the alternate sound buffer and
main screen buffer to be allocated.
• any positive value in 4(A0) causes the alternate sound buffer and
alternate screen buffer to be allocated.
Warning: The sound buffers and alternate screen buffer are not sup-
ported on the Macintosh XL, and the alternate sound and screen buffers
may not be supported in future versions of the Macintosh.
Note: You can get the most recent value passed in 4(A0) to the chain
procedure from the global variable CurPageOption.
Chain closes the resource file for any previous application and opens
the resource file for the application being started; Call DetachResource
for any resources that you still wish to access.
\ Launch
15
Procedure Launch
Trap Macro _Launch
On Entry (A0): Pointer to appl file's name.
4(A0): configuration of sound and screen buffers (word).
Launch is called by the Finder to start up an application and will rarely need to be called by the application itself. It's the same as the Chain procedure except that it frees the storage occupied by the application Heap and restores the heap to its original size.
Note: Launch preserves a special handle in the application Heap which
is used for preserving the Desk Scrap between applications.
\ GetOSEvent
16
Function GetOSEvent (eventMask: INTEGER; VAR theEvent: EventRecord) :
FlushEvents removes events from the event queue as specified by the given event masks. It removes all events of the type or types specified by EventMask, up to but not including the first event of any type specified by StopMask; if the event queue doesn't contain any events of the type specified by eventMask, it does nothing. To remove all events specified by EventMask, use a StopMask value of 0.
At the beginning of your application, it's usually a good idea to call FlushEvents (EveryEvent, 0) to empty the event queue of any stray events that may have been left lying around, such as unprocessed keystrokes typed to the Finder.
PBGetCatInfo gets information about the files and directories in a
file catalog. To determine whether the information is for a file or a
directory, test bit 4 of ioFlAttrib, as described in the section
“CInfoPBRec”. The information that’s returned for files is shown in the
left column, and the corresponding information for directories is shown
in the right column.
If ioFDirIndex is positive, the File Manager returns information
about the file or directory whose directory index is ioFDirIndex in the
directory specified by ioVRefNum (this will be the root directory if a
volume reference number is provided).
If ioFDirIndex is 0, the File Manager returns information about the
file or directory specified by ioNamePtr, in the directory specified by
ioVRefNum (again, this will be the root directory if a volume reference
number is provided).
If ioFDirIndex is negative, the File Manager ignores ioNamePtr and
returns information about the directory specified by ioDirID.
With files, PBGetCatInfo is similar to PBHGetFileInfo but returns
some additional information. If the file is open, the reference number
of the first access path found is returned in ioFRefNum, and the name of
the file is returned in ioNamePtr (unless ioNamePtr is NIL).
For server volume directories, in addition to the normal return parameters the ioACUser field returns the user’s access rights in the following format:
Bit 7 if set, user is not the owner of the directory.
if clear, user is the owner of the directory.
6–3 Reserved; this is returned set to zero.
2 If set, user does not have Make Changes privileges to the
directory. If clear, user has Make Changes privileges to
the directory.
1 If set, user does not have See Files privileges to the
directory. If clear, user has See Files privileges to the
directory.
0 If set, user does not have See Folders privileges to the
directory. If clear, user has See Folders privileges to
the directory.
For example, if ioACUser returns zero for a given server volume directory, you know that the user is the owner of the directory and has complete privileges to it.
Result codes noErr No error
bdNamErr Bad file name
dirNFErr Directory not found or incomplete pathname
extFSErr External file system
fnfErr File not found
ioErr I/O error
nsvErr No such volume
paramErr No default volume
\ PBSetCatInfo
17
Function PBSetCatInfo (paramBlock: CInfoPBPtr; async: BOOLEAN) : OSErr;
<-- lapActCount {number of frame data bytes actually
received}
--> lapDataPtr {pointer to buffer}
LAPRead receives a frame from another node. LAPReqCount and
lapDataPtr specify the length and location of the buffer that will receive the frame data. If the buffer isn't large enough to hold all of the incoming frame data, the extra bytes wil be discarded and buf2SmallErr will be returned. The number of bytes actually received is returned in lapActCount. Only frames with LAP protocol type equal to
lapAddress.lapProtType will be received. The node number of the
frame's source and destination nodes are returned in
lapAddress.srcNodeID and lapAddress.dstNodeID respectively. You can
determine if the packet was broadcast to you by examining the value of
lapAddress.dstNodeID--if the packet was broadcast it's equal to 255,
otherwise it's equal to your node ID.
(note)
You should issue LAPRead calls only for LAP protocol
types that were opened (via LAPOpenProtocol) to use the
default protocol handler.
Result codes
noErr No error
buf2SmallErr Frame too large for buffer
readQErr Invalid protocol type or
protocol type not found in table
\ LAPRdCancel
23
Function LAPRdCancel (abRecord: ABRecHandle) : OSErr;
Given the handle to the ABusRecord of a previously made LAPRead call,
LAPRdCancel dequeues the LAPRead call, provided that a packet
satisfying the LAPRead has not already arrived. LAPRdCancel returns
noErr if the LAPRead call is successfully removed fdrom the queue. If
LAPRdCancel returns recNotFnd, check the abResult field to verify that
the LAPRead has been completed and determine its outcome.
Result codes
noErr No error
readQErr Invalid protocol type or
protocol type not found in table
recNotFnd ABRecord n ot found in queue
\ DDPOpenSocket
23
Function DDPOpenSocket (VAR theSocket: Byte; sktListener: Ptr) : OSErr;
DDPOpenSocket adds a socket and its socket listener to the socket table. If theSocket is nonzero (it must be in the range of 64 to 127),
it specifies the socket's number. If theSocket is 0, DDPOpenSocket dynamically assigns a socket number in the range 128 to 254, and
returns it in theSocket. SktListener contains a pointer to the socket listener; if it's NIL, the default listener will be used.
If you're using the default socket listener, you must then call DDPRead to receive a datagram (in order to specify buffer space for the default socket listener). If, however, you've written your own socket listener and sktListener points to it, your listener will provide buffers for receiving datagrams and you shouldn't use DDPRead calls.
DDPOpenSocket will return ddpSktErr if you pass the number of an already opened socket, if you pass a socket number greater than 127, or
if the socket table is full.
(note)
The range of static socket numbers 1 through 63 is
reserved for use by AppleTalk. Socket numbers 64 through
127 are available for unrestricted experimental use.
Result codes
noErr No error
ddpSktErr Socket error
\ DDPCloseSocket
23
Function DDPCloseSocket (theSocket: Byte) : OSErr;
DDPCloseSocket removes the entry of the specified socket from the
socket table and cancels all pending DDPRead calls that have been made
to close a socket that isn't open, DDPCloseSocket will return
ddpSktErr.
Result codes
noErr No error
ddpSktErr Socket error
\ DDPWrite
23
Function DDPWrite (abRecord: ABRecfHandle; doChecksum: BOOLEAN; async:
BOOLEAN) : OSErr;
ABusRecord
----------
<-- abOpcode {always tDDPWrite}
<-- abResult {result code}
--> abUserReference {for your use}
--> ddpType {DDP protocol type}
--> ddpSocket {source socket number}
--> ddpAddress {destination socket address}
--> ddpReqCount {length of datagram data}
--> ddpDataPtr {pointer to buffer}
DDPWrite sends a datagram to another socket. DDPReqCount and
ddpDataPtr specify the length and location of the data to send. The
ddpType field indicates the DDP protocol type of the frame, and
ddpAddress is the complete internet address of the socket to which the
datagram should be sent. DDPSocket specifies the socket from which the
datagram should be sent. Datagrams sent over the internet to a node on
an AppleTalk network different from the sending node's network have an
optional software checksum to detect errors that might occur inside the
intermediate bridges. If doChecksum is TRUE, DDPWrite will compute
this checksum; if it's FALSE, this software checksum feature is
ignored.
(note)
The destination socket can't be in the same node as the
program making the DDPWrite call.
Result codes
noErr No error
ddpLenErr Datagram length too big
ddpSktErr Source socket not open
\ DDPRead
23
Function DPRead (abRecord: ABRecfHandle; retChecksum: BOOLEAN; async:
BOOLEAN) : OSErr;
ABusRecord
----------
<-- abOpcode {always tDDPWrite}
<-- abResult {result code}
--> abUserReference {for your use}
<-- ddpType {DDP protocol type}
--> ddpSocket {listening socket number}
<-- ddpAddress {source socket address}
--> ddpReqCount {buffer size in bytes}
<-- ddpActCount {number of bytes actually received}
--> ddpDataPtr {pointer to buffer}
<-- ddpNodeID {original destination node ID}
DDPRead receives a datagram from another socket. The length and
location of the buffer that will receive the data are specified by
ddpReqCount and ddpDataPtr, respectively. If the buffer isn't large
enough to hold all of the incoming frame data, the extra bytes will be
discarded and buf2SmallErr will be returned. The numbr of bytes
actually received is returned in ddpActCount. DDPSocket specifies the
socket to receive the datagram (the "listening" socket). The node to
which the packet was sent is returned in ddpNodeID; if the packet was
broadcast ddpNodeID will contain 255. The address of the socket that
sent the packet is returned in ddpAddress. If retCksumErrs is FALSE,
DDPRead will discard any packets received with an invalid checksum and
inform the caller of the error. If retCksumErr is TRUE, DDPRead will
deliver all packets, regardless of whether the checksum is valid or
not; it will also notify the caller when there's a checksum error.
(note)
The sender of the datagram must be in a different node
from the receiver. Youk should issue DDPRead calls only
for receiving datagrams for sockets opened with the
default socket listener; see the description of
DDPOpenSocket.
(note)
If DDPRead returns buf2SmallErr, it will deliver packets
even if retCksukmErrs is FALSE.
Result codes
noErr No error
buf2SmallErr Datagram too large for buffer
cksumErr Checksum error
ddpLenErr Datagram length too big
ddpSktErr Socket error
readQErr Invalid socket or
socket not found in table
\ DDPRdCancel
23
Function DDPRdCancel (abRecord: ABRecHandle) : OSErr;
Given the handle to the ABusRecord of a previously made DDPRead
call, DDPRdCancel dequeues the DDPRead call, provided that a packet
satisfying the DDPRead hasn't already arrived. DDPRdCancel returns
noErr if the DDPRead call is successfully removed from the queue. If
DDPRdCancel returns recNotFnd, check the abResult field of abRecord to
verify that the DDPRead has been completed and determine its outcome.
Result codes
noErr No error
readQErr Invalid socket or socket not found in table
recNotFnd ABRecord not found in queue
\ ATPLoad
23
Function ATPLoad : OSErr;
ATPLoad first verifies that the .MPP driver is loaded and running.
If it isn't, ATPLoad verifies that port B is configured for AppleTalk, and is not in use, and then loads MPP into the system heap.
ATPLoad then loads the .ATP driver, unless it's already in memory.
On a Macintosh 128K, ATPLoad reads the .ATP driver from the system
resource file into the application heap; on a Macintosh 512K or XL, ATP
is read into the system heap.
(note)
On a Macintosh 512K or XL, ATPLoad and MPPOpen perform
essentially the same function.
Result codes
noErr No error
portInUse Port B is already in use
portNotCf Port B not configured for AppleTalk
\ ATPUnload
23
Function ATPUnload : OSErr;
ATPUnload makes the .ATP driver purgeable; the space isn't actually released by the Memory Manager until necessary.
(note)
This call applies only to a Macintosh 128K; on a
Macintosh 512K or Macintosh XL, ATPUnload has no effect.
Result codes
noErr No error
\ ATPOpenSocket
23
Function ATPOpenSocket (addrRcvd: AddrBlock; VAR atpSocket: Byte) :
OSErr;
ATPOpenSocket opens a socket for the purpose of receiving requests. ATPSocket contains the socket number of the socket to open; if it's 0, a number is dynamically assigned and returned in atpSocket. AddrRcvd contains a filter of the sockets from which requests will be accepted. A 0 in the network number, node ID, or socket number field of the addrRcvd record acts as a "wild card"; for instance, a 0 in the socket number field means that requests will be accepted from all sockets in the node(s) specified by the network and node fields.
Result codes
noErr No error
tooManySkts Socket table ful
noDataArea Too many outstanding ATP calls
(note)
If you're only going to send requests and receive
responses to these requests, you don't need to open an
ATP socket. When you make the ATPSndRequest or
ATPRequest call, ATP automatically opens a dynamically
assigned socket for that purpose.
\ ATPCloseSocket
23
Function ATPCLoseSocket (atpSocket: Byte) : OSErr;
ATPCloseSocket closes the responding socket whose number is specified by atpSocket. It releases the data structures associated with all pending, asynchronous calls involving that socket; these pending calls are completed immediately and return the result code sktClosed.
Result codes
noErr No error
noDataArea Too many outstanding ATP calls
\ ATPSndRequest
23
Function ATPSndRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
ABusRecord
----------
<-- abOpcode {always tATPSndRequest}
<-- abResult {result code}
--> abUserReference {for your use}
--> atpAddress {destination socket address}
--> atpReqCount {request size in bytes}
--> atpDataPtr {pointer to buffer}
--> atpRspBDSPtr {pointer to response BDS}
--> atpUserData {user bytes}
--> atpXO {exactly-once flag}
<-- atpEOM {end-of-message flag}
--> atpTimeOut {retry timeout interval in seconds}
--> atpRetries {maximum number of retries}
--> atpNumBufs {number of elements in response BDS}
<-- atpNumRsp {number of response packets actually }
{received}
ATPSndRequest sends a request to another socket. ATPAddress is the internet address of the socket to which the request should be sent. ATPDataPtr and atpReqCount specify the location and size of a buffer that contains the request information to be sent. ATPUserData contains the user bytes for the ATP header.
ATPSndRequest requires you to allocate a response BDS. ATPRspBDSPtr is a pointer to the response BDS; atpNumBufs indicates the number of BDS elements in the BDS (this is also the maximum number of response datagrams that will be accepted). The number of response datagrams actually received is returned in atpNumRsp; if a nonzero value is returned, you can examine the response BDS to determine which packet of the transaction were actually received. If the number returned is less than requested, one of the folowing is true:
- Some of the packets have been lost and the retry count has been
exceeded.
- ATPEOM is TRUE; this means that the response consisted of fewer
packets than were expected, but that all packets sent were
received (the last packet came with the atpEOM flag set).
ATPTimeOut indicates the length of time that ATPSndRequest should wait for a response before retransmitting the request. ATPRetries indicates the maximum number of retries ATPSndRequest shoud attempt. ATPXO should be TRUE if you want the request to be part of an exactly-once transaction.
ATPSndRequest completes when either the transaction is completed or the retry count is exceeded.
Result codes
noErr No error
reqFailed Retry count exceeded
tooManyReqs Too many concurrent requests
noDataArea Too many outstanding ATP calls
\ ATPRequest
23
Function ATPRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
ABusRecord
----------
<-- abOpcode {always tATPRequest}
<-- abResult {result code}
--> abUserReference {for your use}
--> atpAddress {destination socket address}
--> atpReqCount {request size in bytes}
--> atpDataPtr {pointer to buffer}
<-- atpActCount {number of bytes actually received}
--> atpUserData {user bytes}
--> atpXO {exactly-once flag}
<-- atpEOM {end-of-message flag}
--> atpTimeOut {retry timeout interval in seconds}
--> atpRetries {maximum number of retries}
<-- atpRspUData {user bytes received in transaction response
--> atpRspBuf {pointer to response message buffer}
--> atpRspSize {size of response message buffer}
ATPRequest is functionally analogous to ATPSndRequest. It sends a
request to another socket, but doesn't require the caller to set up and
use the BDS data structure to describe the response buffers.
ATPAddress indicates the socket to which the request should be sent.
ATPDataPtr and atpReqCount specify the location and size of a buffer
that contains the request information to be sent. ATPUserData contains
the uset bytes to be sent in the request's ATP header. ATPTimeOut
indicates the length of time that ATPRequest should wait for a response
before retransmitting the request. ATPRetries indicates the maximum
number of retries ATPRequest should attempt.
To use this call, you must have an area of contiguous buffer space that's large enough to receive all expected datagrams. The various
datagrams will be assembled in this buffer and returned to you as a complete message upon completion of the transaction. The address and size of this buffer are pased in atpRspBuf and atpRspSize, respectively. Upon completion of the call, the size ofthe received response message is returned in atpActCount. The user bytes received in the ATP header of the first response packet are returned in atpRspUData. ATPXO should be TRUE if you want the request to be part of an exactly-once transaction.
Although you don't provide a BDS, ATPRequest in fact creates one and calls the .ATP driver (as in an ATPSndRequest call). For this reason, the abRecord fields atpRspBDSPtr and atpNumBufs are used by ATPRequest; you should not expect these fields to remain unaltered during or after the function's execution.
For ATPRequest to receive and correctly deliver the response as a single message, the responding end must, upon receiving the request (with an ATPGetRequest call), generate the complete response as a complete message in a single buffer and then call ATPResponse.
(note)
The responding end could also use ATPSndRsp and ATPAddRsp
provided that each response packet (except the last one)
contains exactly 578 ATP data bytes; the last packet in
the response can contain less than 578 ATP data bytes.
Also, if this method is used, only the ATP user bytes of
the first response packet will be delivered to the
requester; any information in the user bytes of the
remaining response packets will not be delivered.
ATPRequest completes when either the transaction is completed or
the retry count is exceeded.
Result code
noErr No error
reqFailed Retry count exceeded
tooManyReqs Too many concurrent requests
sktClosed Socket closed by a cancel call
noDataArea Too many outstanding ATP calls
\ ATPReqCancel
23
Function ATPReqCancel (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
Given the handle to the ABusRecord of a previously made ATPSndRequest or ATPRequest call, ATPReqCancel dequeues the ATPSndRequest
or ATPRequest call, provided that the call hasn't already completed. ATPReqCancel returns noErr if the ATPSndRequest or ATPRequest call is
successfully removed from the queue. If it returns cbNotFound, check the abResult field of abRecord to verify that the ATPSndRequest or
ATPRequest call has been completed and determine its outcome.
Result codes
noErr No error
cbNotFound ATP control block not found
\ ATPGetRequest
23
Function ATPGetRequest (abRecord: ABRecHandle; async: BOOLEAN) :
OSErr;
ABusRecord
----------
<-- abOpcode {always tATPGetRequest}
<-- abResult {result code}
--> abUserReference {for your use}
--> atpSocket {listening socket number}
<-- atpAddress {source socket address}
--> atpReqCount {buffer size in bytes}
--> atpDataPtr {pointer to buffer}
<-- atpBitMap {transaction bit map}
<-- atpTransID {transaction ID}
<-- atpActCount {number of bytes actually received}
<-- atpUserData {user bytes}
<-- atpXO {exactly-once flag}
ATPGetRequest sets up the mechanism to receive a request sent by
either an ATPSndRequest or an ATPRequest call. ATPSocket contains the
socket number of the socket that should listen for a request; this socket
must already have been opened by calling ATPOpenSocket. The address of the socket from which the request was sent is returned in atpAddress.
ATPDataPtr specifies a buffer to store the incoming request; atpReqCount indicates the size of the buffer in bytes. The number of bytes actually received in the request is returned in atpActCount. ATPUserData contains the user bytes from the ATP header. The transaction bit map is returned in atpBitMap. The transaction ID is returned in atpTransID. ATPXO will be TRUE if the request is part of an exactly-once transaction.
ATPGetRequest completes when a request is received. To cancel an
asynchronous ATPGetRequest call, you must call ATPCloseSocket, but this
cancels all pending calls involving that socket.
Result codes
noErr No error
badATPSkt Bad responding socket
sktClosed Socket closed by a cancel call
\ ATPSndRsp
23
Function ATPSndRsp (abRecord: ABRecHandle; async: BOOLEAN) :
OSErr;
ABusRecord
----------
<-- abOpcode {always tATPSndRsp}
<-- abResult {result code}
--> abUserReference {for your use}
--> atpSocket {responding socket number}
--> atpAddress {destination socket address}
--> atpRspBDSPtr {pointer to response BDS}
--> atpTransID {transaction ID}
--> atpEOM {end-of-message flag}
--> atpNumBufs {number of response packets being sent}
--> atpBDSSize {number of elements in response BDS}
ATPSndRsp sends a response to another socket. ATPSocket contains
the socket number from which the response should be sent and atpAddress
contains the internet address of the socket to which the response
should be sent. ATPTransID must contain the transaction ID. ATPEOM is
TRUE if the response BDS contains the final packet in a transaction
composed of a group of packets and the number of packets in the
response is less than expected. ATPRspBDSPtr points to the buffer data
structure containing the responses to be sent. ATPBDSSize indicates
the number of elements in the response BDS, and must be in the range 1
to 8. ATPNumBufs indicates the number of response packets being sent
with this call, and must be in the range 0 to 8.
(note)
In some situations, you may want to send only part (or
possibly none) of your response message back immediately.
For instance, you might be requested to send back seven
disk blocks, but have only enough internal memory to
store one block. In this case, set atpBDSSize to 7
(total number of response packets), atpNumBufs to 0
(number of response packets currently being sent), and
call ATPSndRsp. Then as you read in one block at a time,
call ATPAddRsp until all seven response datagrams have
been sent.
During exactly-once transactions, ATPSndRsp won't complete until
the release packet is received or the release timer expires.
Result codes
noErr No error
badATPSkt Bad responding socket
noRelErr No release received
sktClosed Socket closed by a cancel call
noDataArea Too many outstanding ATP calls
\ ATPAddRsp
23
Function ATPAddRsp (abRecord: ABRecHandle): OSErr;
ABusRecord
----------
<-- abOpcode {always tATPAddRsp}
<-- abResult {result code}
--> abUserReference {for your use}
--> atpSocket {responding socket number}
--> atpAddress {destination socket address}
--> atpReqCount {buffer size in bytes}
--> atpDataPtr {pointer to buffer}
--> atpTransID {transaction ID}
--> atpUserData {user bytes}
--> atpEOM {end-of-message flag}
--> atpNumRsp {sequence number}
ATPAddRsp sends one additional response packet to a socket that has already been sent the initial part of a response via ATPSndRsp. ATPSocket contains the socket number from which the response should be sent and atpAddress contains the internet add
(note)
No BDS is needed with ATPAddRsp because all pertinent information is passed within the record.
Result codes
noErr No error
badATPSkt Bad responding socket
badBuffNum Bad sequence number
noSendResp ATPAddRsp issued before ATPSndRsp
noDataArea Too many outstanding ATP calls
\ ATPResponse
23
Function ATPResponse (abRecord: ABRecHandle; async: BOOLEAN) :
OSErr;
ABusRecord
----------
<-- abOpcode {always tATPResponse}
<-- abResult {result code}
--> abUserReference {for your use}
--> aptSocket {responding socket number}
--> atpAddress {destination socket address}
--> atpRspUData {user bytes sent in transaction response}
--> atpRspBuf {pointer to response message buffer}
--> atpRspSize {size of response message buffer}
ATPResponse is functionally analogous to ATPSndRsp. It sends a response to a socket, but doesn't require the caller to provide a BDS. ATPAddress must contain the complete network address of the socket to which the response should be sent (the socket on which the corresponding
ATPGetRequest was issued). ATPRspBuf points to the buffer containing the response message; the size of this buffer must be passed in
atpRspSize. The four user bytes to be sent in the ATP header of the first response packet are passed in atpRspUData. The last packet of
the transaction response is sent with the EOM flag set.
Although you don't provide a BDS, ATPResponse in fact creates one and calls the .ATP driver (as in an ATPSndRsp call). For this reason, the abRecord fields atpRspBDSPtr and atpNumBufs are used by ATPResponse; you should not expect these fields to remain unaltered during or after the function's execution.
During exactly-once transactions ATPResponse won't complete until the release packet is received or the release timer expires.
(warning)
The maximum permissible size of the response message is
4624 bytes.
Result codes
noErr No error
badATPSkt Bad responding socket
noRelErr No release received
atpLenErr Response too big
sktClosed Socket closed by a cancel call
noDataArea Too many outstanding ATP calls
\ ATPRspCancel
23
Function ATPRspCancel (abRecord: ABRecHandle; async: BOOLEAN) :
OSErr;
Given the handle to the ABusRecord of a previously made ATPSndRsp or ATPResponse call, ATPRspCancel dequeues the ATPSndRsp or ATPResponse call, provided that the call hasn't already completed. ATPRspCancel returns noErr if the ATPSndRsp or ATPResponse call is successfully removed from the queue. If it returns cbNotFound, check the abResult field of abRecord to verify that the ATPSndRsp or ATPResponse call has been completed and determine its outcome.
Result codes
noErr No error
cbNotFound ATP control block not found
noDataArea Too many outstanding ATP calls
\ NBPRegister
23
Function NBPRegister (abRecord: ABRecHandle; async: BOOLEAN) :
NBPRegister adds the name and address of an entity to the node's
names table. NBPEntityPtr points to a variable of type EntityName
containing the entity's name. If the name is already registered,
NBPRegister returns the result code nbpDuplicate. NBPBufPtr and nbpBufSize specify the location and size of a buffer for NBP to use internally. The buffer must contain at least 12 bytes plus the length of the entity name.
(warning)
This buffer must not be altered or released until the
name is removed from the names table via an NBPRemove
call. If you allocate the buffer through a NewHandle
call, the handle must be locked as long as the name is
registered.
Result codes
noErr No error
nbpDuplicate Duplicate name already exists
\ NBPLookup
23
Function NBPLookup (abRecord: ABRecHandle; async: BOOLEAN) :
NBPLookup returns the addresses of all entities with a specified name. NBPEntityPtr points to a variable of type EntityName containing the name of the entity whose address should be returned. (Meta-characters are allowed in the entity name.) NBPBufPtr and NBPBufSize contain the location and size of an area of memory in which the entities' addresses should be returned. NBPDataField indicates the maximum number of matching names to find addresses for; the actual number of addresses
found is returned in NBPDataField. NBPRetransmitInfo contains the
retry interval and the retry count.
Result codes
noErr No error
nbpBuffOvr Buffer overflow
\ NBPExtract
23
Function NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne:
INTEGER; VAR abEntityName; VAR address: AddrBlock)
: OSErr;
NBPExtract retruns one address from the list of addresses returned by NBPLookup. TheBuffer and numInBuf indicate the location and number of
tuples in the buffer. WhichOne specifies which one of the tuples in
the buffer should be returned in the abEntity and adress parameters.
Result codes
noErr No error
extractErr Can't find tuple in buffer
\ NBPConfirm
23
Function NBPConfirm (abRecord: ABRecHandle; async: BOOLEAN) :
NBPConfirm confirms that an entity known by name and address still
exists (is still entered in the names directory). NBPEntityPtr points
to a variable of type EntityName that contains the name to confirm, and
nbpAddress specifies the address to be confirmed. (No meta-characters
are allowed in the entity name.) NBPRetransmitInfo contains the retry
interval and the retry count. The correct socket number of the entity
is returned in nbpDataField. NBPConfirm is more efficient than
NBPLookup in terms of network traffic.
Result codes
noErr No error
nbpConfDiff Name confirmed for different socket
nbpNoConfirm Name not confirmed
\ NBPRemove
23
Function NBPRemove (abEntity: EntityPtr) : OSErr;
NBPRemove removes an entity name from the names table of the caller's node.
Result codes
noErr No error
nbpNotFound Name not found
\ NBPLoad
23
Function NBPLoad : OSErr;
On a Macintosh 128K, NBPLoad reads the AppleTalk Manager's NBP code
from the system resource file into the application heap. On a Macintosh 512K or XL, NBPLoad has no effect since the NBP code should have already been loaded when the .MPP driver was opened. Normally you'll never need to call NBPLoad because the AppleTalk Manager calls it when necessary.
Result codes noErr No error
\ NBPUnload
23
Function NBPUnload : OSErr;
NBPUnload makes the NBP code purgeable; the space isn't actually
released by the Memory Manager until necessary.
(note)
This call applies only to a Macintosh 128K; on a
Macintosh 512K or Macintosh XL, NBPUnload has no effect.
Result codes noErr No error
\ GetNodeAddress
23
Function GetNodeAddress (VAR myNode,myNet: INTEGER) : OSErr;
GetNodeAddress returns the current node ID and network number of the
caller. If the .MPP driver isn't installed, it returns noMPPErr. If
myNet contains 0, this means that a bridge hasn't yet been found.
Result codes
noErr No error
noMPPErr MP driver not installed
\ IsMPPOpen
23
Function IsMPPOpen : BOOLEAN;
IsMPPOpen returns TRUE if the .MPP driver is loaded and running.
\ IsATPOpen
23
Function IsATPOpen : BOOLEAN;
IsATPOpen returns TRUE if the .ATP driver is loaded and running.
Call LActivate to activate or deactivate the list specified by
lHandle (in response to an activate event in the window containing the
list). The act parameter should be set to TRUE to activate the list, or
FALSE to deactivate the list. LActivate highlights or unhighlights the
selections, and shows or hides the scroll bars (but not the size box, if
any).
\ Reset
27
Procedure Reset( F, [,title] );
F is a variable of type file; if title is given the file must not be open. If the title is not given, the file must be open. Title is expression with a string value.
Reset(f) when f is already open causes f to be rewound. If f was open with rewrite then f becomes read-only. Reset(f, title) finds an existing file with name title an associate f to this file.
After Reset, if the file is empty then Eof(f) is true and f^ undefined else Eof(f) is false and f^ contains the first component of the file.
\ Rewrite
27
Procedure Rewrite( F, [,title] );
F is a variable of type file; if title is given the file must not be open. If the title is not given, the file must be open. Title is expression with a string value.
Rewrite(f) if f is not yet open, create an empty anonymous file. Rewrite(f) if f is already open, rewound the file to the beginning and empties it. If f was originally open with reset the file becoms write-only.
Rewrite(f,title) creates a new empty file. If a file with this name already exists, it is deleted.
After Rewrite :
- Eof(f) is true .
- F^ is undefined .
\ Open
27
Procedure Open (f, title);
F is a variable of type file; f must not be already open. Title is expression with a string value. If no file with this name exists, a new empty file is created. The file F is opened for both reading and writing.
After Rewrite
- Eof(f) is true if the file is empty.
- f^ contains the first component if Eof(f) is false.
\ Close
27
Procedure Close(f);
F is a variable of type file; f must be open and must not be an anonymous file.
After Close, F^ becomes undefined.
\Eof
27
Function EOF [(F)] :Boolean;
F is a variable of type file; f must be open. If F is ommited f is the standard input file.
Eof returns true if the file position is behind the last component of the file or if the file is empty.
After a put Eof is true if the component written is now the last component of the file. So, on write-only files Eof is always true.
\ Get
27
Procedure Get(f);
F is a variable of type file; f must be open. Get advances the file position to the next component and assigns its vaalue to f^. If no next component exists the eof(f) becomes true.
\ Put
27
Procedure Put(f);
F is a variable of type file; f must be open.
Put writes the value of F^ at the current file position and advances the file position to the next component. If no next component exists the eof(f) becomes true. F^ becomes undefined.
\ Seek
27
Procedure Seek(f,n);
F is a variable of type file; f must be open with an open call.
n is an integer specifying the new file position.
After Seek F^ is the value on the nth component ( numbered from 0 ) unless Eof(f) is true ( when n is greater than the number of components in the file ).
Warning: Seek on devices is not allowed.
\ FilePos
27
Function FilePos(f):LongInt;
F is a variable of type file; f must be open. FilePos returns the file component number of the the current file position.
\ Length
28
Function Length(st:String):Integer;
Returns the length of the string.
\ Pos
28
Function Pos(SubStr,Str:String):Integer;
Search for substr within str, and returns an integer value that is the index of the first character of substr withinin str. If substr is not found 0 is return.
\ Concat
28
Function Concat(str1,str2 ...Strn:String):String;
Concatenate all the parameters in the order in which they are written.
\ Copy
28
Function Copy(s:string; index,count:integer):String;
Returns a string containing count characters from s, beginning at s[index]. If count≤0 then '' is returned. If count+index>Length(s) then only the last Length(s)-index+1 characters are copied.
Remove all characters of s from s. only characters in the range 1..Length(s) are deleted.
\ Omit
28
Function Omit(s:string; index,count:integer):String;
Idem to delete but the destination is the function result instead of the source.
\ Insert
28
Procedure insert( source : String; var Dest:String;index:integer);
Inserts source into dest before the character specified by index. If index<=1 the source is inserted at the left of dest. If index>length(Dest) the source is inserted at the right of dest.
\ Globals By Name
30
Global Variables sorted By Name:
ABusVars $2D8 Pointer to AppleTalk variables
ACount $A9A Stage number (0-3) of last alert (Word)
ANumber $A98 Resource ID of last alert (word)
ApFontID $984 Font number of application font (word)
ApplLimit $130 Application heap limit
ApplScratch $A78 12-byte scratch area reserved for use by
applications
ApplZone $2AA Address of Application heap zone
AppParmHandle $AEC Handle to Finder information
AtMenuBottom $B28 Flag for menu scrolling (word).
AuxCtlHead $CD4 Auxiliary control list header (long).
AuxWinHead $CD0 Auxiliary window list header (long).
BootDrive $210 Working directory reference number for system
startup volume.
BufPtr $10C Address of end of jump table
BufTgDate $304 File tags buffer: Date and time of last mod.
(long)
BufTgFBkNum $302 File tags buffer: logical block number (word)
BufTgFFlg $300 File tags buffer: flags (word: bit 1=1 if
resource fork)
BufTgFNum $2FC File tags buffer: file number (long)
CaretTime $2F4 Caret-blink interval in ticks (long)
CPUFlag $12F Microprocessor in use
CrsrThresh $8EC Mouse-scaling threshold (word)
CurActivate $A64 Pointer to window to receive activate event
CurApName $910 Name of current application (string[31])
CurApRefNum $900 Reference number of current applicatin's
resource file
CurDeactive $A68 Pointer to window to receive deactivate event
CurDirStore $398 Directory ID of directory last opened (long)
CurJTOffset $934 Offset to jump table from location pointed
by A5 (word)
CurMap $A5A Reference number of current resource file (word)
CurPageOption $936 Sound/Screen buffer configuration passed to
chain or launch (word)
CurPitch $280 Value of count in square-wave synthetiser
buffer (word)
CurrentA5 $904 address of boundary between application globals
and application parameters
CurStackBase $908 Address of base of stack; start of application
globals
DABeeper $A9C Address of current sound procedure
DAStrings $AA0 Handle to ParamText strings (16 bytes)
DefltStack $322 Default space allotment for stack (long)
DefVCBPtr $352 Pointer to default volume control block
DeskHook $A6C Address of procedure for painting desktop or
responding to click on desktop
DeskPattern $A3C Pattern with which desktop is painted (8 bytes)
DlgFont $AFA Font number for dialogs and alerts (word)
DoubleTime $2F0 double click interval in ticks (long)
DragHook $9F6 Address of procedure to execute during
TrackGoAway, DragWindow, GrowWindow, DragGrayRg,
TrackControl, and DragControl.
DragPattern $A34 Pattern of dragged region's outline
DrvQHdr $308 Drive queue header (10 bytes)
DSAlertRect $3F8 Rectangle enclosing system error alert (8 bytes)
DSAlertTab $2BA Pointer to system error alert table in use
dsStknHeap 28 stack has moved into application heap
dsReinsert 30 request user to reinsert off-line volume
dsNotThe1 31 not the disk I wanted
negZcbFreeErr 33 ZcbFree has gone negative
menuPrgErr 84 happens when a menu is purged
\ OpenCPort
2
Procedure OpenCPort (port: CGrafPtr);
The OpenCPort procedure is analogous to OpenPort, except it opens a cGrafPort instead of a grafPort. You will rarely need to use this call, since OpenCPort is called by NewCWindow and GetNewCWindow, as well as by the Dialog Manager when the appropriate color resources are present. OpenCPort allocates storage for all the structures in the cGrafPort, and then calls InitCPort to initialize them. The new structures allocated are the portPixMap, the pnPixPat, the fillPixPat, the bkPixPat, and the grafVars handle. The GrafVars record structure is shown below:
TYPE
GrafVars = RECORD
rgbOpColor: RGBColor; {color for addPin, subPin, and blend}
rgbHiliteColor: RGBColor; {color for highlighting}
pmFgColor: Handle; {Palette handle for foreground color}
pmFgIndex: INTEGER; {index value for foreground}
pmBkColor: Handle; {Palette handle for background color}
pmBkIndex: INTEGER; {index value for background}
pmFlags: INTEGER; {Flags for Palette Manager}
END;
The rgbOpColor field is initialized as black, and the rgbHiliteColor field is initialized as the default HiliteRGB. All the rest of the GrafVars fields are initially zero.
The portPixMap is not allocated a color table of its own. When InitCPort is called, the handle to the current device’s color table is copied into the portPixMap.
\ InitCPort
2
Procedure InitCPort (port: CGrafPtr);
The InitCPort procedure does not allocate any storage. It merely initializes all the fields in the cGrafPort to their default values. All old fields are initialized to the same values as a grafPort’s fields. New fields are given the following values:
portPixMap: copied from theGDevice^^.GDPMap
portVersion: $C000
grafVars: opColor initialized to black, rgbHiliteColor initialized
as default HiliteRGB. All other fields are initialized
as 0.
chExtra: 0
pnLocHFrac: 1/2
bkPixPat: white
rgbFgColor: black
rgbBkColor: white
pnPixPat: black
fillPixPat: black
The default portPixMap is set to be the same as the current device’s pixMap. This allows you to create an offscreen port that is identical to the screen’s grafPort or cGrafPort for drawing offscreen. If you want to use a different set of colors for offscreen drawing, you should create a new gDevice, and set it as the current gDevice before opening the cGrafPort. Refer to the section on offscreen bitMaps in the Graphics Devices chapter for more details.
As mentioned above, InitCPort does not copy the data from the current device’s color table to the portPixMap’s color table. It simply replaces whatever is in the pmTable field with a copy of the handle to the current device’s color table.
If you try to initialize a grafPort using InitCPort, it will simply return without doing anything.
\ CloseCPort
2
Procedure CloseCPort (port: CGrafPtr);
CloseCPort releases the memory allocated to the cGrafPort. It disposes of the visRgn, the clipRgn, the bkPixPat, the pnPixPat, the fillPixPat, and the grafVars handle. It also disposes of the portPixMap, but doesn’t dispose of the portPixMap’s color table (which is really owned by the gDevice). If you have placed your own color table into the portPixMap, either dispose of it before calling CloseCPort, or store another reference to it for other uses.
\ RGBForeColor
2
Procedure RGBForeColor (color : RGBColor);
These two calls set the foreground and background colors to the best available match for the current device. The only drawing operations that aren’t affected by these colors are PlotCIcon, and drawing using the new color patterns. Before you call CopyBits with a pixMap as the source, you should set the foreground to black and the background to white.
If the current port is a cGrafPort, the specified RGB is placed in the rgbFgColor or rgbBkColor field (and the pixel value most closely matching that color is placed in the fgColor or bkColor field). If the current port is a grafPort, fgColor or bkColor is set to the old QuickDraw color determined by taking the high bit of each of the R, G, and B components, and using that three-bit number to select one of the eight QuickDraw colors. The ordering of the QuickDraw colors is shown in the GetForeColor description.
\ RGBBackColor
2
Procedure RGBBackColor (color : RGBColor);
These two calls set the foreground and background colors to the best available match for the current device. The only drawing operations that aren’t affected by these colors are PlotCIcon, and drawing using the new color patterns. Before you call CopyBits with a pixMap as the source, you should set the foreground to black and the background to white.
If the current port is a cGrafPort, the specified RGB is placed in the rgbFgColor or rgbBkColor field (and the pixel value most closely matching that color is placed in the fgColor or bkColor field). If the current port is a grafPort, fgColor or bkColor is set to the old QuickDraw color determined by taking the high bit of each of the R, G, and B components, and using that three-bit number to select one of the eight QuickDraw colors. The ordering of the QuickDraw colors is shown in the GetForeColor description.
\ GetForeColor
2
Procedure GetForeColor (VAR color : RGBColor);
see GetBackColor.
\ GetBackColor
2
Procedure GetBackColor (VAR color : RGBColor);
These two calls return the RGB components of the foreground and background colors set in the current port. The calls work for both grafPorts and cGrafPorts. If the current port is a cGrafPort, the returned value is taken directly from the rgbFgColor or rgbBkColor field. If the current port is a grafPort, then only eight possible RGB values can be returned. These eight values are determined by the values in a global variable named QDColors, which is a pointer to a color table containing the current QuickDraw colors.
The colors are stored in the following order:
Value Color Red Green Blue
0 black $0000 $0000 $0000
1 yellow $FC00 $F37D $052F
2 magenta $F2D7 $0856 $84EC
3 red $DD6B $08C2 $06A2
4 cyan $0241 $AB54 $EAFF
5 green $0000 $8000 $11B0
6 blue $0000 $0000 $D400
7 white $FFFF $FFFF $FFFF
This is the set of colors that Color QuickDraw uses to determine precisely what colors should be displayed by an old grafPort that is using color. The default set of colors has been adjusted to match the colors produced on the ImageWriter II printer.
The SetCPixel function sets the pixel at the specified position to the pixel value that most closely matches the specified RGB.
\ NewPixMap
2
Function NewPixMap : PixMapHandle;
The NewPixMap function creates a new, initialized pixMap data structure and returns a handle to it. All fields of the pixMap are copied from the current device’s pixMap except the color table. A handle to the color table is allocated but not initialized.
\ DisposPixMap
2
Procedure DisposPixMap (pm: PixMapHandle);
The DisposPixMap procedure releases all storage allocated by NewPixMap. It disposes of the pixMap’s color table, and of the pixMap itself. Be careful not to dispose of a pixMap whose color table is the same as the current device’s color table.
\ CopyPixMap
2
Procedure CopyPixMap (srcPM,dstPM: PixMapHandle);
The CopyPixMap routine is used for duplicating the pixMap data structure. CopyPixMap copies the contents of the source pixMap data structure to the destination pixMap data structure. The contents of the color table are copied, so the destination pixMap has its own copy of the color table. Since the baseAddr field of the pixMap is a pointer, the pointer, but not the image itself, is copied.
CopyBits now accepts either bitMaps or pixMaps as parameters. For convenience, just as you could pass the current port^.portBits as a parameter to CopyBits, you can now pass GrafPtr(cPort)^.portBits. (Recall that in a cGrafPort the high two bits of the portVersion field are set. This field, in the same position in the port as portBits.rowBytes, indicates to QuickDraw that it has been passed a portPixMap handle.)
This call transfers an image from one bitMap or pixMap to another bitMap or pixMap. The source and destination may be of different depths, of different sizes, and they may have different color tables. Note, however, that the destination pixMap is assumed to use the same color table as the gDevice. (This is because an inverse table is required for translation to the destination’s color table.)
During a CopyBits call, the foreground and background colors are applied to the image. To avoid unwanted coloring of the image, set the foreground to black and the background to white before calling this routine.
CopyMask is a new version of the CopyBits procedure, introduced in the Macintosh Plus. It transfers an image from the source to the destination only where the corresponding bit of the mask equals 1. The Macintosh II version will accept either a bitMap or pixMap as the srcBits or dstBits parameters. The maskBits parameter must be a bitMap.
Like the Macintosh Plus version, CopyMask doesn’t send any of its drawing commands through grafProc routines; thus CopyMask calls are not recorded in pictures. Unlike the Macintosh Plus version, the Macintosh II version of CopyMask is able to stretch the source and mask to fit the dstRect. The srcRect and maskRect should be the same size. CopyMask uses the same low-level code as CopyBits, so all the same rules regarding depth translation and color table translation apply.
During a CopyMask call, the foreground and background colors are applied to the image. To avoid unwanted coloring, set the foreground to black and the background to white before calling this routine.
The SeedCFill procedure generates a mask for use with CopyMask or CopyBits, with bits equal to 1 only in those positions where paint can leak from the starting seed point, like the MacPaint® bucket tool.
Given a rectangle within a source bitMap or pixMap (srcBits), SeedCFill returns a mask (dstBits) that contains 1’s in place of all pixels to which paint can leak from the specified seed position (seedH, seedV), expressed in the local coordinate system of the source pixMap. By default, paint can leak to all adjacent pixels whose RGB value exactly match that of the seed. To use this default, set matchProc and matchData to zero.
In generating the mask, SeedCFill performs CopyBits to convert srcBits to a one-bit mask. It installs a default searchProc into the gDevice that returns 0 if the RGB value matches that of the seed; all other RGB values return 1’s.
If you want to customize SeedCFill, your application can specify a matchProc that is used instead of the default searchProc. It should return 0’s for RGB values that you want to be filled, and 1’s for values that shouldn’t be filled. When the matchProc is called, the GDRefCon field of the current gDevice contains a pointer to a record having the following structure:
MatchRec = RECORD
red: INTEGER;
green: INTEGER;
blue: INTEGER;
matchData: LONGINT
END;
In this record the red, green, and blue fields are the RGB of the pixel at the specified seed location. MatchData is simply whatever value you passed to SeedCFill as a parameter. For instance, your application could pass a handle to a color table whose entries should all be filled, and then, in the matchProc, check to see if the specified RGB matches any of the colors in the table.
No automatic scaling is performed: the source and destination rectangles must be the same size. Calls to SeedCFill are not clipped to the current port and are not stored into QuickDraw pictures.
This routine generates a mask (dstBits) corresponding to the area in a pixMap (srcBits) to which paint cannot leak from outside of the srcRect. The size of srcRect must be the same as the size of dstRect. By default, paint can leak to all adjacent pixels whose RGB values don’t match that of the seedRGB. To use this default, set matchProc and matchData to 0.
For instance, if srcBits contains a blue rectangle on a red background, and your application calls CalcCMask with the seedRGB equal to blue, then the returned mask has ones in the positions corresponding to the edges and interior of the rectangle, and zeros outside of the rectangle.
If you want to customize CalcCMask, your application can specify a matchProc that is used instead of the default searchProc. It should return 1’s for RGB values that define the edges of the mask, and 0’s for values that don’t.
When the matchProc is called, the GDRefCon field of the gDevice contains a pointer to a MatchRec record (the structure shown in the SeedCFill description). The red, green, and blue fields are the RGB of the pixel at the specifed seed location. MatchData is simply whatever value your application passed to CalcCMask as a parameter. For instance, your program could pass a handle to a color table whose entries should all be within the mask, and then, in the matchProc, check to see if the specified RGB matches any of the colors in the table.
No automatic scaling is performed: the source and destination rectangles must be the same size. Calls to CalcCMask are not clipped to the current port and are not stored into QuickDraw pictures.
\ NewPixPat
2
Function NewPixPat: PixPatHandle;
The NewPixPat function creates a new pixPat data structure, and returns a handle to it. It calls NewPixMap to allocate and initialize the pattern’s pixMap to the same settings as theGDevice^^.GDPMap, and it sets the type of the pixPat to be a color pattern. The pat1Data field is initialized to a 50% gray pattern. New handles for data, expanded data, expanded map, and color table are allocated but not initialized. Including the pixPat itself, it allocates a total of six handles. You will generally not need to use this routine since the GetPixPat routine can be used to read in a pattern from a resource file.
The sizes of the pixMap and pixPat handles are the size of their respective data structures (see the type declarations in the “Summary” section). The other three handles are initially small in size. Once the pattern is drawn, the size of the expanded data is proportional to the size of the pattern data, but adjusted to the depth of the screen. The color table size is the size of the record structure plus eight bytes times the number of colors in the table.
Creating a PixPat
To create a color pattern, use NewPixPat to allocate a new PixPatHandle. Set the rowBytes, bounds, and pixelSize of the pattern’s pixMap to the dimensions of the desired pattern. The rowBytes should be equal to (width of bounds)*pixelSize/8; it need not be even. The width and height of the bounds must be a power of two. Each scanline of the pattern must be at least one byte in length—that is, (width of bounds)*pixelSize must be at least eight. Set the other fields in the pattern’s pixMap as described in the section on the pixMap data structure.
Your application can explicitly specify the color corresponding to each pixel value with the color table. The color table for the pattern must be placed in the pmTable in the pixPat’s pixMap. Patterns may also contain colors that are relative to the foreground and background at the time that they are drawn. Refer to the section on the pixPat data structure for more information on relative patterns.
\ DisposPixPat
2
Procedure DisposPixPat (ppat: PixPatHandle);
The DisposPixPat procedure releases all storage allocated by NewPixPat. It disposes of the pixPat’s data handle, expanded data handle, and pixMap handle.
\ CopyPixPat
2
Procedure CopyPixPat (srcPP,dstPP: PixPatHandle);
The CopyPixPat procedure copies the contents of the source pixPat to the destination pixPat. It entirely copies all fields in the source pixPat, including the contents of the data handle, expanded data handle, expanded map, pixMap handle, and color table.
\ GetPixPat
2
Function GetPixPat (patID: INTEGER): PixPatHandle;
The GetPixPat call creates a new pixPat data structure, and then uses the information in the resource of type 'ppat' and the specified ID to initialize the pixPat. The 'ppat' resource format is described in the section “Color QuickDraw Resource Formats”. If the resource with the specified ID is not found, then this routine returns a NIL handle.
The MakeRGBPat procedure is a new call which generates a pixPat that approximates the specified color when drawn. For example, if your application is drawing to a device that has 4 bits per pixel, you will only get 16 colors if you simply set the foreground color and draw. If you use MakeRGBPat to select a pattern, and then draw using that pattern, you will effectively get 125 different colors. More colors are theoretically possible; this implementation opted for a fast pattern selection rather than the best possible pattern selection. If the device has 8 bits per pixel, you will effectively get 2197 colors.
Note that these patterns aren’t usually solid; they provide a wide selection of colors by alternating between colors with up to four colors in a pattern. For this reason lines that are one pixel wide may not look good using these patterns. For an RGB pattern, the patMap^^.bounds always contains (0, 0, 8, 8), and the patMap^^.rowbytes equals 2. Figure 5 shows how these colors are arranged.
When MakeRGBPat creates a color table, it only fills in the last colorSpec field: the other colorSpec values are computed at the time the drawing actually takes place, using the current pixel depth for the system.
Value RGB
0 computed RGB color
1 computed RGB color
2 computed RGB color
3 computed RGB color
4 RGBColor passed to MakeRGBPat routine
\ PenPixPat
2
Procedure PenPixPat (ppat: PixPatHandle);
see BackPixPat.
\ BackPixPat
2
Procedure BackPixPat (ppat: PixPatHandle);
The PenPixPat and BackPixPat calls are analogous to PenPat and BackPat, but use multicolor pixel patterns instead of old-style patterns. If you try to use a pixel pattern in a grafPort, the data in the pat1Data field is placed into pnPat, bkPat, or fillPat.
When your application sets a pixel pattern, the handle you provide is actually placed into the grafPort or cGrafPort. In this way, QuickDraw can expand the pattern once (saving it in the patXData field) when the pattern is first set, and won’t have to reexpand it each time you set the pattern.
Since your handle is actually stored in the grafPort or cGrafPort, it’s considered bad form to dispose of a PixPatHandle that is currently set as the pnPixPat or bkPixPat. (Just in case you forget, QuickDraw will remove all references to your pattern from existing grafPorts or cGrafPorts when you dispose of it.)
Using the old calls PenPat and BackPat, you can still set old-style patterns in a cGrafPort. If necessary, it creates a new pixPatHandle in which to store the pattern (because, as described above, pixPatHandles are owned by the application). As in old grafPorts, old-style patterns are drawn using the foreground and background colors at the time of drawing, not at the time the pattern is set.
\ GetCCursor
2
Function GetCCursor (crsrID: INTEGER): CCrsrHandle;
The GetCCursor call creates a new CCrsr data structure, then initializes it using the information in the resource of type 'crsr' with the specified ID. The 'crsr' resource format is described in the section “Color QuickDraw Resource Formats”. If the resource with the specified ID isn’t found, then this routine returns a NIL handle.
Since GetCCursor creates a new CCrsr data structure each time it is called, your application shouldn’t call GetCCursor before each call to SetCCursor (unlike the way GetCursor/SetCursor were normally used). GetCCursor doesn’t dispose or detach the resource, so resources of type 'crsr' should typically be purgeable.
\ SetCCursor
2
Procedure SetCCursor (cCrsr: CCrsrHandle);
The SetCCursor procedure allows your application to set a multicolor cursor. At the time the cursor is set, it’s expanded to the current screen depth so that it can be drawn rapidly.
If your application has changed the cursor’s data or its color table, it must also invalidate the fields crsrXValid and crsrID (described in the section on the Color Cursor data structure), before calling SetCCursor.
\ DisposCCursor
2
Procedure DisposCCursor(cCrsr: CCrsrHandle);
The DisposCCursor procedure disposes all structures allocated by GetCCursor.
\ AllocCursor
2
Procedure AllocCursor;
The AllocCursor procedure reallocates cursor memory. Under normal circumstances, you should never need to use this call, since reallocation of cursor memory is only necessary after the depth of one of the screens has been changed.
\ GetCIcon
2
Function GetCIcon(id: INTEGER): CIconHandle;
The GetCIcon function allocates a CIcon data structure and initializes it using the information in the resource of type 'cicn' with the specified ID. It returns the handle to the icon’s data structure. If the specified resource isn’t found, a NIL handle is returned.
The format of the 'cicn' resource is described in the section “Color QuickDraw Resource Formats”.
Since GetCIcon creates a new CIcon data structure each time it is called, your application shouldn’t call GetCIcon before each call to PlotCIcon. GetCIcon doesn’t dispose or detach the resource, so resources of type 'cicn' should typically be purgeable.
\ DisposCIcon
2
Procedure DisposCIcon(theIcon: CIconHandle);
The DisposCIcon procedure disposes all structures allocated by GetCIcon.
The PlotCIcon procedure draws the specified icon in the specified rectangle. The iconMask field of the CIcon determines which pixels of the iconPMap are drawn and which are not. Only pixels with 1’s in corresponding positions in the iconMask are drawn; all other pixels don’t affect the destination. If the screen depth is one or two bits per pixel, the iconBMap is used as the source instead of the iconPMap (unless the rowBytes field of iconBMap is 0, indicating that there is no iconBMap.
When the icon is drawn, the boundsRect of the iconPMap is used as the image’s source rectangle. The icon and its mask are both stretched to the destination rectangle. The icon’s pixels are remapped to the current depth and color table, if necessary. The bounds fields of the iconPMap, iconBMap, and iconMask are expected to be equal in size.
PlotCIcon is simply a structured call to CopyMask. As such, it doesn’t send any of its drawing commands through grafProc routines; thus, PlotCIcon calls are not recorded in pictures.
\ SetPortPix
2
Procedure SetPortPix (pm: PixMapHandle);
The SetPortPix call is analogous to SetPortBits, and should be used instead of SetPortBits for cGrafPorts. It replaces the portPixMap field of the current cGrafPort with the specified handle. SetPortPix has no effect when used with an old grafPort. If SetPortBits is called when the current port is a cGrafPort, it does nothing.
\ OpColor
2
Procedure OpColor (color: RGBColor);
If the current port is a cGrafPort, the OpColor procedure sets the red, green, and blue values used by the AddPin, SubPin, and Blend drawing modes. This information is actually stored in the grafVars handle in the cGrafPort, but you should never need to reference it directly. If the current port is a grafPort, OpColor has no effect.
\ HiliteColor
2
Procedure HiliteColor (color:RGBColor);
The highlight color is used by all drawing operations that use the highlight transfer mode. When a cGrafPort is created, its highlight color is initialized from the global variable HiliteRGB. The HiliteColor procedure allows you to change the highlighting color used by the current port. This information is actually stored in the grafVars handle in the cGrafPort, but you should never need to reference it directly. If the current port is a grafPort, HiliteColor has no effect.
\ CharExtra
2
Procedure CharExtra (extra:Fixed);
The CharExtra procedure sets the cGrafPort’s charExtra field, which specifies the number of pixels by which to widen every character excluding the space character in a line of text. The charExtra field is stored in a compressed format based on the txSize field, so you must set txSize before calling CharExtra. The initial charExtra setting is 0. CharExtra will accept a negative number. CharExtra has no effect on grafPorts.
\ SetStdCProcs
2
Procedure SetStdCProcs (VAR cProcs: CQDProcs);
This procedure sets all the fields of the given CQDProcs record to point to the standard low-level routines. You can then change the ones you wish to point to your own routines. For example, if your procedure that processes picture comments is named MyComments, you will store @MyComments in the commentProc field of the CQD Procs record.
When drawing in a cGrafPort, your application must always use SetStdCProcs instead of SetStdProcs.
\ GetCTable
2
Function GetCTable (ctID: INTEGER): CTabHandle;
The GetCTable routine allocates a new color table data structure, and initializes it using the information in the resource of type 'clut' having the specified ID. If the specified resource is not found, a NIL handle is returned.
If you place this handle into a pixMap, you should first dispose of the handle that was already there.
The format of the 'clut' resource is given in the section “Color QuickDraw Resource Formats”. Resource ID values 0..127 are reserved for system use. Any 'clut' resources defined by your application should have IDs in the range 128..1023. This value must be in the ctSeed field in the resource, and will be placed in the ctSeed field of the color table (for color table identification). All other possible seed values are used to identify newly created color tables, and color tables that have been modified.
If you modify a color table, you should invalidate it by changing its ctSeed field. You can get a new unique value for ctSeed using the routine GetCTSeed, described in the Color Manager chapter.
\ DisposCTable
2
Procedure DisposCTable(cTable: CTabHandle);
The DisposCTable procedure disposes the handle allocated for a color table.
\ Color2Index
42
Function Color2Index (rgb: RGBColor): LONGINT;
The Color2Index routine finds the best available approximation to a given absolute color, using the list of search procedures in the current device record. It returns a longint, which is a pixel value padded with zeros in the high word. Since the colorSpec.value field is only a word, the result returned from Color2Index must be truncated to fit into a colorSpec. In pixMaps the .value is the low-order word of this index.
Color2Index shouldn’t be called from a custom search procedure.
\ Index2Color
42
Procedure Index2Color (index: LONGINT; VAR rgb: RGBColor);
The Index2Color routine finds the RGB color corresponding to a given color table index. The desired pixel value is passed and the corresponding RGB value is returned in RGB. The routine takes a longint, which should be a pixel value padded with zeros in the high word (normally the compiler does this automatically). Normally, the RGB from the current device color table corresponding to the index is returned as the RGBColor. Notice that this is not necessarily the same color that was originally requested via RGBForeColor, RGBBackColor, SetCPixel, or Color2Index. This RGB is read from the current gDevice color table.
\ InvertColor
42
Procedure InvertColor (VAR theColor: RGBColor);
The InvertColor routine finds the complement of an absolute color, using the list of complement procedures in the current device record. The default complement procedure uses the 1’s complement of each component of the requested color.
\ RealColor
42
Function RealColor (color: RGBColor) : BOOLEAN;
The RealColor routine tells whether a given absolute color actually exists in the current device’s color table. This decision is based on the current resolution of the inverse table. For example, if the current iTabRes is four, RealColor returns TRUE if there exists a color that exactly matches the top four bits of red, green, and blue.
The GetSubTable routine takes a ColorTable pointed at by myColors, and maps each RGB value into its nearest available match for each target table. These best matches are returned in the colorSpec.value fields of myColors. The values returned are best matches to the RGBColor in targetTbl and the returned indices are indices into targetTbl. Best matches are calculated using Color2Index and all applicable rules apply. A temporary inverse table is built, and then discarded. ITabRes controls the resolution of the iTable that is built. If targetTbl is NIL, then the current device’s color table is used, and the device’s inverse table is used rather than building a new one. To provide a different resolution than the current inverse table, provide an explicit targetTbl parameter; don’t pass a NIL parameter.
Warning: Depending on the requested resolution, building the inverse table can require large amounts of temporary space in the application heap: twice the size of the table itself, plus a fixed overhead for each inverse table resolution of 3–15K bytes.
The MakeITable routine generates an inverse table based on the current contents of the color table pointed to by CTabHandle, with a resolution of res bits per channel. Reserved color table pixel values are not included in the resultant color table. MakeITable tests its input parameters and will return an error in QDError if the resolution is less than three or greater than five. Passing a NIL parameter to CTabHandle or ITabHandle substitutes an appropriate handle from the current gDevice, while passing 0 for res substitutes the current gDevice’s preferred table resolution. These defaults can be used in any combination with explicit values, or with NIL parameters.
This routine allows maximum precision in matching colors, even if colors in the color table differ by less than the resolution of the inverse table. Five-bit inverse tables are not needed when drawing in normal QuickDraw modes. However, the new QuickDraw transfer modes (add, subtract, blend, etc.) may require a 5-bit inverse table for best results with certain color tables. MakeITable returns a QDError if the destination inverse table memory cannot be allocated. The 'mitq' resource governs how much memory is allocated for temporary internal structures; this resource type is for internal use only.
Warning: Depending on the requested resolution, building the inverse table can require large amounts of temporary space in the application heap: twice the size of the table itself, plus a fixed overhead for each inverse table resolution of 3–15K bytes.
\ GetCTSeed
42
Function GetCTSeed : LONGINT;
The GetCTSeed function returns a unique seed value that can be used in the ctSeed field of a color table created by an application. This seed value guarantees that the color table will be recognized as distinct from the destination, and that color table translation will be performed properly. The return value will be greater than the value stored in minSeed.
The ProtectEntry procedure protects or removes protection from an entry in the current device’s color table, depending on the value of the protect parameter. A protected entry can’t be changed by other clients. It returns a protection error if it attempts to protect an already protected entry. However, it can remove protection from any entry.
The ReserveEntry procedure reserves or dereserves an entry in the current color table, depending on the value of the reserve parameter. A reserved entry cannot be matched by another client’s search procedure, and will never be returned to another client by Color2Index or other routines that depend on it (such as RGBForeColor, RGBBackColor, SetCPixel, and so forth). You could use this routine to selectively protect a color for color table animation.
ReserveEntry copies the low byte of gdID into the low byte of ColorSpec.value when reserving an entry, and leaves the high byte alone. It acts like a selective protection, and does not allow any changes if the current gdID is different than the one in the colorSpec.value field of the reserved entry. If a requested match is already reserved, ReserveEntry returns a protection error. Any entry can be dereserved.
The SetEntries procedure sets a group of color table entries for the current gDevice, starting at a given position for the specified number of entries. The pointer aTable points into a cSpecArray, not into a color table. The colorSpec.value field of the entries must be in the logical range for the target card’s assigned pixel depth. Thus, with a 4-bit pixel size, the colorSpec.value fields should be in the range 1 to 15. With an 8-bit pixel size the range is 0 to 255. Note that all values are zero-based; for example, to set three entries, pass two in the count parameter.
Note: Palette Manager routines should be used instead of the SetEntries routine for applications that will run in a multiscreen or multitasking environment.
The SetEntries positional information works in logical space, rather than in the actual memory space used by the hardware. Requesting a change at position four in the color table may not modify color table entry four in the hardware, but it does correctly change the color on the screen for any pixels with a value of four in the video card. The SetEntries mode characterized by a start position and a length is called sequence mode. In this case, new colors are sequentially loaded into the hardware in the same order as the aTable, the clientID fields for changed entries are copied from the current device’s gdID field, and the colorSpec.value fields are ignored.
The other SetEntries mode is called index mode. It allows the cSpecArray to specify where the data will be installed on an entry-by-entry basis. To use this mode, pass –1 for the start position, with a valid count and a pointer to the cSpecArray. Each entry is installed into the color table at the position specified by the colorSpec.value field of each entry in the cSpecArray. In the current device’s color table, all changed entries’ colorSpec.value fields are assigned the gdID value.
When color table entries are changed, all cached fonts are invalidated, and the seed number is changed so that the next drawing operation will rebuild the inverse table. If any of the requested entries are protected or out of range, a protection error is returned, and nothing happens. If a requested entry is reserved, it can only be changed if the current gdID matches the low byte of the intended ColorSpec.value field.
\ SaveEntries
42
Procedure SaveEntries (srcTable: CTabHandle; ResultTable: CTabHandle; VAR selection: ReqListRec);
SaveEntries saves a selection of entries from srcTable into resultTable. The entries to be set are enumerated in the selection parameter, which uses the ReqListRec data structure shown below. (These values are offsets into colorTable, not the contents of the colorSpec.value field.)
TYPE
ReqListRec = RECORD
reqLSize: INTEGER; {request list }
{ size –1}
reqLData: ARRAY [0..0] of INTEGER {request list }
{ data}
END;
If an entry is not present in srcTable, then that position of the requestList is set to colReqErr, and that position of resultTable has random values returned. If one or more entries are not found, then an error code is posted to QDError; however, for every entry in selection which is not colReqErr, the values in resultTable are valid. Note that srcTable and selection are assumed to have the same number of entries.
SaveEntries optionally allows NIL as its source color table parameter. If NIL is used, the current device’s color table is used as the source. The output of SaveEntries is the same as the input for RestoreEntries, except for the order.
\ RestoreEntries
42
Procedure RestoreEntries (srcTable:CTabHandle;DstTable:CTabHandle; VAR selection:RecListRec);
RestoreEntries sets a selection of entries from srcTable into dstTable, but doesn’t rebuild the inverse table. The dstTable entries to be set are enumerated in the selection parameter, which uses the ReqListRec data structure shown in the SetEntries routine description. (These values are offsets into the srcTable, not the contents of the colorSpec.value field.)
If a request is beyond the end of the dstTable, that position of the requestList is set to colReqErr, and an error is returned. Note that srcTable and selection are assumed to have the same number of entries.
If dstTbl is NIL, or points to the device color table, the current device’s color table is updated, and the hardware is updated to these new colors. The seed is not changed, so no invalidation occurs (this may cause RGBForeColor to act strangely). This routine ignores protection and reservation of color table entries.
Generally, the Palette Manager is used to give an application its own set of colors; use of RestoreEntries should be limited to special-purpose applications. RestoreEntries allows you to change the colorTable without changing the ctSeed for the affected colorTable. You can execute the application code and then use RestoreEntries to put the original colors back in. However, in some cases things in the background may appear in the wrong colors, since they were never redrawn. To avoid this, the application must build its own new inverse table and redraw the background. If RestoreEntries were then used, the ctSeed would have to be explicitly changed to clean up correctly.
\ SearchProc
42
Function SearchProc (rgb: RGBColor; VAR position: LONGINT): BOOLEAN;
When attempting to approximate a color, the Color Manager calls each search procedure in the list until the boolean value returns as TRUE. The index value of the closest match is returned by the position parameter. If no search procedure installed in the linked list returns TRUE, the Color Manager calls the default search procedure.
The application can also supply a custom complement procedure to find the complement of a specified color. Complement procedures work the same as search procedures, and are kept in a list beginning in the gDevice port’s gdCompProc field.
TYPE
CProcHndl = ^CProcPtr;
CProcPtr = ^CProcRec;
CProcRec = RECORD
nxtComp: CProcHandle; {pointer to next }
{ CProcRec}
compProc: ProcPtr {pointer to complement }
{ procedure}
END;
The default complement procedure simply uses the 1’s complement of the RGB color components before looking them up in the inverse table. The interface is as follows:
\ CompProc
42
Procedure CompProc (VAR rgb: RGBColor);
Operations on Search and Complement Procedures
\ AddSearch
42
Procedure AddSearch (searchProc: ProcPtr);
The AddSearch routines add a procedure to the head of the current device record’s list of search or complement procedures. These routines allocate an SProcRec or CProcRec.
\ AddComp
42
Procedure AddComp (compProc: ProcPtr);
The AddComp routines add a procedure to the head of the current device record’s list of search or complement procedures. These routines allocate an SProcRec or CProcRec.
\ DelSearch
42
Procedure DelSearch (searchProc: ProcPtr);
The DelSearch procedures remove a custom search or complement procedure from the current device record’s list of search or complement procedures. These routines dispose of the chain element, but do nothing to the procPtr.
\ DelComp
42
Procedure DelComp (compProc: ProcPtr);
The DelComp procedures remove a custom search or complement procedure from the current device record’s list of search or complement procedures. These routines dispose of the chain element, but do nothing to the procPtr.
\ SetClientID
42
Procedure SetClientID (id: INTEGER);
The SetClientID procedure sets the gdID field in the current device record to identify this client program to its search and complement procedures.
\ NewGDevice
44
Function NewGDevice(refNum: INTEGER; mode: LONGINT) GDHandle;
The NewGDevice function allocates a new gDevice data structure and all of its handles, then calls InitGDevice to initialize it for the specified device in the specified mode. If the request is unsuccessful, a NIL handle is returned. The new gDevice and all of its handles are allocated in the system heap. All attributes in the GDFlags word are set to FALSE.
If your application creates a gDevice without a driver, the mode parameter should be set to –1. In this case, InitGDevice is not called to initialize the gDevice. Your application must perform all initialization.
A graphics device’s default mode is defined as 128, as described in the Designing Cards and Drivers manual; this is assumed to be a monochrome mode. If the mode parameter is not the default mode, the gdDevType attribute is set TRUE, to indicate that the device is capable of displaying color (see the SetDeviceAttribute call).
This routine doesn’t automatically insert the gDevice into the device list. In general, your application shouldn’t add devices that it created to the device list.
The InitGDevice routine sets the video device whose driver has the specified gdRefNum to the specified mode. It then fills out the gDevice record structure specified by the gdh parameter to contain all information describing that mode. The GDHandle should have been allocated by a call to NewGDevice.
The mode determines the configuration of the device; possible modes for a device can be determined by interrogating the video card’s ROM via calls to the Slot Manager (refer to the Slot Manager chapter and the Designing Cards and Drivers manual). Refer to the Device Manager chapter for more details about the interaction of devices and their drivers.
The information describing the new mode is primarily contained in the video card’s ROM. If the device has a fixed color table, then that table is read directly from the ROM. If the device has a variable color table, then the default color table for that depth is used (the 'clut' resource with ID=depth).
In general, your application should never need to call this routine. All video devices are initialized at start time and their modes are changed by the control panel. If your program is initializing a device without a driver, this call will do nothing; your application must initialize all fields of the gDevice. It is worth noting that after your program initializes the color table for the device, it needs to call MakeITable to build the inverse table for the device.
\ GetGDevice
44
Function GetGDevice: GDHandle;
The GetGDevice routine returns a handle to the current gDevice. This is useful for determining the characteristics of the current output device (for instance its pixelSize or color table). Note that since a window can span screen boundaries, this call does not return the device that describes a port.
Assembly-language note: A handle to the currently active device is kept in the global variable TheGDevice.
\ SetGDevice
44
Procedure SetGDevice(gdh: GDHandle);
The SetGDevice procedure sets the specified gDevice as the current device. Your application won’t generally need to use this call except to draw to offscreen gDevices.
\ DisposGDevice
44
Function DisposGDevice: GDHandle;
The DisposGDevice function disposes of the current gDevice and releases the space allocated for it, and all data structures allocated by NewGDevice.
\ GetDeviceList
44
Function GetDeviceList: GDHandle;
The GetDeviceList function returns a handle to the first device in the DeviceList.
Assembly-language note: A handle to the first element in the device list is kept in the global variable DeviceList.
\ GetMainDevice
44
Function GetMainDevice: GDHandle;
The GetMainDevice function returns the handle of the gDevice that has the menu bar on it. Your application can examine this gDevice to determine the size or depth of the main screen.
Assembly-language note: A handle to the current main device is kept in the global variable MainDevice.
\ GetNextDevice
44
Function GetNextDevice (gdh: GDHandle): GDHandle;
The GetNextDevice function returns the handle of the next gDevice in the DeviceList. If there are no more devices in the list, it returns NIL.
The SetDeviceAttribute routine can be used to set a device’s attribute bits. The following attributes may be set using this call:
gdDevType = 0; {0 = monochrome, 1 = color}
ramInit = 10; {set if device has been initialized from RAM}
mainScreen = 11; {set if device is main screen}
allInit = 12; {set if devices were initialized from a }
{ 'scrn' resource}
screenDevice= 13; {set if device is a screen device}
noDriver = 14; {set if device has no driver}
screenActive= 15; {set if device is active}
\ TestDeviceAttribute
44
Function TestDeviceAttribute (curDevice: GDHandle; attribute: INTEGER) : BOOLEAN;
The TestDeviceAttribute function tests a single attribute to see if it is true or not. If your application is scanning through the device list, it would typically use this routine to test if a device is a screen device, and if so, test to see if it’s active. Then your application can draw to any active screen devices.
\ GetMaxDevice
44
Function GetMaxDevice (globalRect: Rect):GDHandle;
The GetMaxDevice routine returns a handle to the deepest device that intersects the specified global rectangle. Your application might use this routine to allocate offscreen pixMaps, as described in the following section.
\ OpenXPP
23
Function OpenXPP(VAR xppRefnum: INTEGER): OSErr;
\ ASPOpenSession
23
Function ASPOpenSession(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPCloseSession
23
Function ASPCloseSession(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPAbortOS
23
Function ASPAbortOS(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPGetParms
23
Function ASPGetParms(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPCloseAll
23
Function ASPCloseAll(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPUserWrite
23
Function ASPUserWrite(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPUserCommand
23
Function ASPUserCommand(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ ASPGetStatus
23
Function ASPGetStatus(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ AFPCommand
23
Function AFPCommand(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
\ PAttachPH
23
Function PAttachPH(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PDetachPH
23
Function PDetachPH(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PWriteLAP
23
Function PWriteLAP(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ POpenSkt
23
Function POpenSkt(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PCloseSkt
23
Function PCloseSkt(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PWriteDDP
23
Function PWriteDDP(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PRegisterName
23
Function PRegisterName(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PLookupName
23
Function PLookupName(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PConfirmName
23
Function PConfirmName(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PRemoveName
23
Function PRemoveName(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PKillNBP
23
Function PKillNBP(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ PSetSelfSend
23
Function PSetSelfSend(thePBptr:MPPPBptr;async:BOOLEAN): OSErr;
\ POpenATPSkt
23
Function POpenATPSkt(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PCloseATPSkt
23
Function PCloseATPSkt(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PSendRequest
23
Function PSendRequest(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PGetRequest
23
Function PGetRequest(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PSendResponse
23
Function PSendResponse(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PAddResponse
23
Function PAddResponse(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PRelTCB
23
Function PRelTCB(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PRelRspCB
23
Function PRelRspCB(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PNSendRequest
23
Function PNSendRequest(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PKillSendReq
23
Function PKillSendReq(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
\ PKillGetReq
23
Function PKillGetReq(thePBptr:ATPPBptr;async:BOOLEAN): OSErr;
The NewCWindow routine creates a new color window. This routine is similar to the old routine NewWindow, but creates a window based on a cGrafPort instead of an old-style grafPort.
The GetNewCWindow routine creates a new color window from a template in a resource file. It’s analogous to the old routine GetNewWindow, but it creates a window based on a cGrafPort instead of an old-style grafPort. GetNewCWindow checks the 'wctb' resource, and if it contains the same resource ID, it colors the window. The backColor of the window is set to the new content color. This allows an application to begin its update with an EraseRect without changing the background color.
The SetWinColor routine sets a window’s color table. If the window currently has no auxiliary window record, a new one is created with the given color table and added to the head of the auxiliary window list. If there is already an auxiliary record for the window, its color table is replaced by the contents of newColorTable. The window is then automatically redrawn in the new colors. If SetWinColor is performed on a cWindow, it sets the backColor of the window to the new content color. This allows an application to begin its update without changing the background color.
If newColorTable has the same contents as the default color table, the window’s existing auxiliary record and color table are removed from the auxiliary window list and deallocated. If theWindow = NIL, the operation modifies the default color table in memory. The system never disposes of color tables that are resources when the resource bit is set; 'wctb' resources can’t be purgeable.
\ GetAuxWin
5
Function GetAuxWin (theWindow: WindowPtr; VAR colors: CTabHandle) : BOOLEAN; [Macintosh II]
The GetAuxWin routine returns a handle to a window’s auxiliary window record:
- If the given window has an auxiliary record, its handle is returned in colors and the function returns TRUE.
- If the window has no auxiliary record, a handle to the default record is returned in colors and the function returns FALSE.
- If theWindow = NIL, a handle to the default record is returned in colors and the function returns TRUE.
\ GetWVariant
5
Function GetWVariant (whichWindow:WindowPtr): INTEGER; [Macintosh Plus, Macintosh SE, Macintosh II]
GetWVariant returns the variant code for the window described by whichWindow. See the Window Manager chapter in Volume I for more information about variants.
\ GetGrayRgn
5
Function GetGrayRgn : regionHandle; [Macintosh Plus, Macintosh SE, Macintosh II]
The GetGrayRgn function returns a handle to the current desktop region stored in the global variable GrayRgn.
A new Dialog Manager routine has been added to support color dialogs: NewCDialog. Its parameters are identical to NewDialog, except that a cGrafPort is allocated through a NewCWindow call instead of a call to NewWindow.
NewCDialog creates a dialog box as specified by its parameters and returns a cDialogPtr to the new dialog. The first eight parameters (dStorage through refCon) are passed to the Window Manager function NewCWindow, which creates the dialog window. The items parameter is a handle to the dialog’s item list. You can get the items handle by calling the Resource Manager to read the item list from the resource file into memory.
After calling NewCDialog, you can use SetWinColor to add a color table to the dialog. This creates an auxiliary window record (auxWinRec) for the dialog window. You can access this record with the GetAuxWin routine. The dialogCItem handle within the auxWinRec points to the dialog item color table.
If the dialog’s content color isn’t white, it’s a good idea to call NewCDialog with the visible flag set to FALSE. After the color table and color item list are installed, use ShowWindow to display the dialog if the dialog is the frontmost window. If the dialog is not in front, use ShowHide to display the dialog.
\ PrStlInit
18
Function PrStlInit(hPrint: THPrint): TPPrDlg;
\ PrJobInit
18
Function PrJobInit(hPrint: THPrint): TPPrDlg;
\ PrDlgMain
18
Function PrDlgMain(hPrint: THPrint; pDlgInit: ProcPtr): Boolean;
\ PrGeneral
18
Procedure PrGeneral (pData: Ptr);
The pData parameter is a pointer to a data block. The structure of the data block is declared as follows:
TGnlData = RECORD
{1st 8 bytes are common for all PrGeneral calls);
iOpCode: Integer; {input}
iError: Integer; {output}
lReserved: LongInt; {reserved for future use}
{more fields here, depending on particular call}
END;
The first field in the TGnlData record is a 2-byte opcode, iOpCode, which acts somewhat like a routine selector. The currently available opcodes are these:
- GetRslData (get resolution data): iOpCode = 4
- SetRsl (set resolution): iOpCode = 5
- DraftBits (bitmaps in draft mode): iOpCode = 6
- NoDraftBits (no bitmaps in draft mode): iOpCode = 7
- GetRotn (get rotation): iOpCode = 8
GetRslData and SetRsl allow the application to find out what physical resolutions the printer supports, and then specify a supported resolution. DraftBits and noDraftBits invoke a new feature of the ImageWriter, allowing bitmaps (imaged via CopyBits) to be printed in draft mode. GetRotn lets an application know whether landscape orientation has been selected. These routines are described in the next sections.
The second field in the TGnlData record is the error result, iError, returned by the print code. This error only reflects error conditions that occur during the PrGeneral call. For example, if you use an opcode that isn’t implemented in a particular printer driver then you will get an OpNotImpl error. Here are the error codes:
CONST
NoErr = 0; {no error}
NoSuchRsl = 1; {the resolution you chose isn't available}
OpNotImpl = 2; {the driver doesn't support this opcode}
After calling PrGeneral you should always check PrError. If NoErr is returned, then you can proceed. If ResNotFound is returned, then the current printer driver doesn’t support PrGeneral and you should proceed appropriately.
IError is followed by a four byte reserved field. The contents of the rest of the data block depends on the opcode that the application uses.
GetRslData
GetRslData (iOpCode = 4) returns a record that lets the application know what resolutions are supported by the current printer. The application can then use SetRsl to tell the printer driver which one it will use. These calls introduce a good deal of complexity into your application’s code, and should be used only when necessary.
This is the format of the input data block for the GetRslData call:
TRslRg = RECORD {used in TGetRslBlk}
iMin: Integer; {0 if printer supports only discrete resolutions}
iMax: Integer; {0 if printer supports only discrete resolutions}
END;
TRslRec = RECORD {used in TGetRslBlk}
iXRsl: Integer; {a discrete, physical X resolution}
iYRsl: Integer; {a discrete, physical Y resolution}
END;
TGetRslBlk = RECORD {data block for GetRslData call}
iOpCode: Integer; {input; = getRslDataOp}
iError: Integer; {output}
lReserved: LongInt; {reserved for future use}
iRgType: Integer; {output; version number}
XRslRg: TRslRg; {output; range of X resolutions}
YRslRg: TRslRg; {output; range of Y resolutions}
iRslRecCnt: Integer; {output; how many RslRecs follow}
rgRslRec: ARRAY[1..27] OF TRslRec; {output; number filled }
{ depends on printer type}
END;
The iRgType field is much like a version number; it determines the interpretation of the data that follows. An iRgType value of 1 applies both to the LaserWriter and to the ImageWriter.
For variable-resolution printers like the LaserWriter, the resolution range fields XRslRg and YRslRg express the ranges of values to which the X and Y resolutions can be set. For discrete-resolution printers like the ImageWriter, the values in the resolution range fields are zero.
Note: In general, X and Y in these records are the horizontal and vertical directions of the printer, not the document. In “landscape” orientation, X is horizontal on the printer but vertical on the document.
After the resolution range information there is a word which gives the number of resolution records that contain information. These records indicate the physical resolutions at which the printer can actually print dots. Each resolution record gives an X value and a Y value.
Notice that all the resolution range numbers are the same for this printer. There is only one resolution record, which gives the physical X and Y resolutions of the printer (300 x 300).
All the resolution range values are zero, because only discrete resolutions can be specified for the ImageWriter. There are four resolution records giving these discrete physical resolutions.
GetRslData always returns the same information for a particular printer type—it is not dependent on what the user does or on printer configuration information.
SetRsl
SetRsl (iOpCode = 5) is used to specify the desired imaging resolution, after using GetRslData to determine a workable pair of values. Below is the format of the data block:
TSetRslBlk = RECORD {data block for SetRsl call}
iOpCode: Integer; {input; = setRslOp}
iError: Integer; {output}
lReserved: LongInt; {reserved for future use}
hPrint: THPrint; {input; handle to a valid print record}
iXRsl: Integer; {input; desired X resolution}
iYRsl: Integer; {input; desired Y resolution}
END;
The hPrint parameter contains the handle of a print record that has previously been passed to PrValidate. If the call executes successfully, the print record is updated with the new resolution; the data block comes back with 0 for the error and is otherwise unchanged. If the desired resolution is not supported, the error is set to noSuchRsl and the resolution fields are set to the printer’s default resolution
You can undo the effect of a previous call to SetRsl by making another call that specifies an unsupported resolution (such as 0 x 0), forcing the default resolution.
DraftBits
DraftBits (iOpCode = 6) is implemented on both the ImageWriter and the LaserWriter. On the LaserWriter it does nothing, because the LaserWriter is always in draft mode and can always print bitmaps. Here is the format of the data block:
TDftBitsBlk = RECORD {data block for DraftBits and NoDraftBits calls}
iOpCode: Integer; {input; = draftBitsOp or noDraftBitsOp}
iError: Integer; {output}
lReserved: LongInt; {reserved for future use}
hPrint: THPrint; {input; handle to a valid print record}
END;
The hPrint parameter contains the handle of a print record that has previously been passed to PrValidate.
This call forces draft-mode (immediate) printing, and will allow bitmaps to be printed via CopyBits calls. The virtue of this is that you avoid spooling large masses of bitmap data onto the disk, and you also get better performance.
The following restrictions apply:
- This call should be made before bringing up the print dialog boxes because it affects their appearance. On the ImageWriter, calling DraftBits disables the landscape icon in the Style dialog, and the Best, Faster, and Draft buttons in the Job dialog box.
- If the printer does not support draft mode, already prints bitmaps in draft mode, or does not print bitmaps at all, this call does nothing.
- Only text and bitmaps can be printed.
- As in the normal draft mode, landscape format is not allowed.
- Everything on the page must be strictly Y-sorted; that is, no reverse paper motion between one string or bitmap and the next. This means you can’t have two or more objects (text or bitmaps) side by side; the top boundary of each object must be no higher than the bottom of the preceding object.
The last restriction is important. If you violate it, you will not like the results. However, if you want two or more bitmaps side by side, you can combine them into one before calling CopyBits to print the result. Similarly, if you are just printing bitmaps you can rotate them yourself to achieve landscape printing.
NoDraftBits
NoDraftBits (iOpCode = 7) is implemented on both the ImageWriter and the LaserWriter. On the LaserWriter it does nothing, since the LaserWriter is always in draft mode and can always print bitmaps. The format of the data block is the same as that for the DraftBits call. This call cancels the effect of any preceding DraftBits call. If there was no preceding DraftBits call, or the printer does not support draft-mode printing anyway, this call does nothing.
GetRotn
GetRotn (iOpCode = 8) is implemented on the ImageWriter and LaserWriter. Here is the format of the data block:
TGetRotnBlk = RECORD {data block for GetRotn call}
iOpCode: Integer; {input; = getRotnOp}
iError: Integer; {output}
lReserved: LongInt; {reserved for future use}
hPrint: THPrint; {input; handle to a valid print record}
fLandscape: Boolean; {output; Boolean flag}
bXtra: SignedByte; {reserved}
END;
The hPrint parameter contains a handle to a print record that has previously been passed to PrValidate.
If landscape orientation is selected in the print record, then fLandscape is true.
Using PrGeneral
SetRsl and DraftBits calls may require the print code to suppress certain options in the Style and/or Job dialog boxes, therefore they should always be called before any call to the Style or Job dialogs. An application might use PrGeneral as follows:
- Get a new print record by calling PrintDefault, or take an existing one from a document and call PrValidate on it.
- Call GetRslData to find out what the printer is capable of, and decide what resolution to use. Check PrError to be sure the PrGeneral call is supported on this version of the print code; if the error is ResNotFound, you have older print code and must print accordingly. But if the PrError return is 0, proceed as follows:
- Call SetRsl with the print record and the desired resolution if you wish.
- Call DraftBits to invoke the printing of bitmaps in draft mode if you wish.
If you call either SetRsl or DraftBits, you should do so before the user sees either of the printing dialog boxes.
The SetStylHandle procedure sets an edit record’s style handle, stored in the txFont and txFace fields. SetStylHandle has no effect on an old-style edit record. Applications should always use SetStylHandle rather than manipulating the fields of the edit record directly.
\ GetStylHandle
8
Function GetStylHandle (hTE: TEHandle) : TEStyleHandle;
The GetStylHandle function gets an edit record’s style handle, stored in the txFont and txFace fields. GetStylHandle returns NIL when used with an old-style edit record. Applications should always use this function rather than manipulating the fields of the edit record directly.
\ GetStylScrap
8
Function GetStylScrap (hTE: TEHandle) : StScrpHandle;
The GetStylScrap routine allocates a block of type StScrpRec and copies the style information associated with the current selection into it. This is the same as TECopy, except that no action is performed on the text, and the handle to the 'styl' scrap is output in this case. Unlike TECopy, the StScrpRec is not copied to the desk scrap.
GetStylScrap will return a NIL value if called with an old style TEHandle, or if the selection is NIL (stylStart equals stylEnd).
The TEStylInsert procedure takes the specified text and inserts it just before the selection range into the text indicated by hTE, redrawing the text as necessary. If hST is not NIL and hTE is a TextEdit record created using TEStylNew, the style information indicated by hST will also be inserted to correspond with the inserted text. When hST is NIL and/or hTE has not been created using TEStylNew, there is no difference between this procedure and TEInsert. TEStylInsert does not affect either the current selection range or the scrap.
\ TEGetOffset
8
Function TEGetOffset (pt: Point; hTE: TEHandle) : INTEGER;
The TEGetOffset routine finds the character offset in an edit record’s text corresponding to the given point. TEGetOffset works for both old-style and new-style edit records.
\ TEGetPoint
8
Function TEGetPoint (offset: INTEGER; hTE: TEHandle) : POINT;
The TEGetPoint routine returns the point corresponding to the given offset into the text. The point returned is to the bottom (baseline) left of the character at the specified offset. TEGetPoint works for both old- and new-style edit records.
\ TEGetHeight
8
Function TEGetHeight (endLine, startLine: LONGINT; hTE: TEHandle) : INTEGER;
The TEGetHeight routine returns the total height of all the lines in the text between and including startLine and endLine. TEGetHeight works for both old- and new-style edit records.
\ TEGetStyle
8
Procedure TEGetStyle (offset: INTEGER; VAR theStyle: TextStyle;
VAR lineHeight,fontAscent: INTEGER; hTE: TEHandle);
The TEGetStyle procedure returns the style information, including line height and font ascent, associated with a given character in an edit record’s text. For an old-style edit record, it returns the record’s global text characteristics.
\ TEStylPaste
8
Procedure TEStylPaste (hTE: TEHandle);
The TEStylPaste procedure pastes text from the desk scrap into the edit record’s text at the current insertion point or replaces the current selection. The text is styled according to the style information found in the desk scrap; if there is none, it is given the same style as the first character of the replaced selection (or that of the preceding character if the selection is an insertion point). In an old-style edit record, just the text is pasted without its accompanying style.
The TESetStyle procedure sets the style of the current selection to that specified by newStyle. ( It has no effect on an old-style edit record.) The mode parameter controls which style attributes to set; it may be any additive combination of the following constants:
CONST
doFont = 1; {set font (family) number}
doFace = 2; {set character style}
doSize = 4; {set type size}
doColor = 8; {set color}
doAll = 15; {set all attributes}
addSize = 16; {adjust type size}
In the last case (addSize), the value of newStyle.tsSize is added to all type sizes within the current selection instead of replacing them; this value may be either positive or negative. (If present, addSize overrides doSize.) If redraw = TRUE, the affected text will be redrawn in the new style.
The TEReplaceStyle procedure replaces the style specified by oldStyle with that given by newStyle within the current selection. (It has no effect on an old-style edit record.) The mode parameter takes the same values as TESetStyle (above), except that addSize has no meaning here. All styles for which the combination of attributes designated by mode have the values given by oldStyle are changed to have the corresponding values from newStyle instead. Style changes are made directly to the style-table elements within the table itself. If mode = doAll, newStyle simply replaces oldStyle outright.
Initialize the CursorCtl unit. This should be called once prior to calling RotateCursor or SpinCursor. It need not be called if only Hide_Cursor or Show_Cursor are used. If NewCursors is NULL, InitCursorCtl loads in the 'acur' resource and the 'CURS' resources specified by the 'acur' resource ids. If any of the resources cannot be loaded, the cursor will not be changed.
The 'acur' resource is assumed to either be in the currently running tool or application, or the MPW Shell for a tool, or in the System file. The 'acur' resource id must be 0 for a tool or application, 1 for the Shell, and 2 for the System file.
If NewCursors is not NULL, it is ASSUMED to be a handle to an 'acur' formatted resource designated by the caller and it will be used instead of doing a GetResource on 'acur'. Note, if RotateCursor or SpinCursor are called without calling InitCursorCtl, then RotateCursor and SpinCursor will do the call for the user the first time it is called. However, the possible disadvantage of using this technique is that the resource memory allocated may have undesirable affect (fragmentation?) on the application. Using InitCursorCtl has the advantage of causing the allocation at a specific time determined by the user.
Caution: InitCursorCtl MODIFIES the 'acur' resource in memory. Specifically, it changes each FrameN/fillN integer pair to a handle to the corresponding 'CURS' resource also in memory. Thus if NewCursors is not NULL when InitCursorCtl is called, the caller must guarantee NewCursors always points to a "fresh" copy of an 'acur' resource. This need only be of concern to a caller who wants to repeatly use multiple 'acur' resources during execution of their programs.
\ RotateCursor
32
Procedure RotateCursor(counter: LONGINT);
RotateCursor is called to rotate the "I am active" "beach ball" cursor, or to animate whatever sequence of cursors set up by InitCursorCtl. The next cursor ("frame") is used when Counter % 32 = 0 (Counter is some kind of incrementing or decrementing index maintained by the caller). A positive counter sequences forward through the cursors (e.g., it rotates the "beach ball" cursor clockwise), and a negative cursor sequences through the cursors backwards (e.g., it rotates the "beach ball" cursor counterclockwise). Note, RotateCursor just does a Mac SetCursor call for the proper cursor picture.
It is assumed the cursor is visible from a prior Show_Cursor call.
\ SpinCursor
32
Procedure SpinCursor(increment: INTEGER);
SpinCursor is similar in function to RotateCursor, except that instead of passing a counter, an Increment is passed an added to a counter maintained here. SpinCursor is provided for those users who do not happen to have a convenient counter handy but still want to use the spinning "beach ball" cursor, or any sequence of cursors set up by InitCursorCtl. A positive increment sequences forward through the curos (rotating the "beach ball" cursor clockwise), and a negative increment sequences backward through the cursors (rotating the "beach ball" cursor counter-clockwise). A zero value for the increment resets the counter to zero. Note, it is the increment, and not the value of the counter that determines the sequencing direction of the cursor (and hence the spin direction of the "beach ball" cursor).\ Hide_Cursor
32
Procedure Hide_Cursor;
Hide the cursor if it is showing.This is this unit's call to the Mac HideCursor routine.Thus the Mac cursor level is decremented by one when this routine is called.\ Show_Cursor
32
Procedure Show_Cursor(cursorKind: Cursors);
Increment the cursor level, which may have been decremented by Hide_Cursor, and display the specified cursor if the level becomes 0 (it is never incremented beyond 0).The CursorKind is the kind of cursor to show. It is one of the values HIDDEN_CURSOR, I_BEAM_CURSOR, CROSS_CURSOR, PLUS_CURSOR, WATCH_CURSOR, and ARROW_CURSOR. Except for HIDDEN_CURSOR, a Mac SetCursor is done for the specified cursor prior to doing a ShowCursor. HIDDEN_CURSOR just causes a ShowCursor call. Note, ARROW_CURSOR will only work correctly if there is already a grafPort set up pointed to by 0(A5).
ErrMgr initialization.This must be done before using any other ErrMgr routine. Set showToolErrNbrs to true if you want all tool messages to contain the error number following the message text enclosed in parentheses (e.g., "<msg txt> ([OS] Error <n>)"; system error messages always contain the error number). The toolErrFileName parameter is used to specify the name of a tool-specific error file, and should be the NULL or a null string if not used (or if the tool's data fork is to be used as the error file, see GetToolErrText for futher details). The sysErrFileName parameter is used to specify the name of a system error file, and should normally be the NULL or a null string, which causes the ErrMgr to look in the MPW Shell directory for "SysErrs.Err" (see GetSysErrText).
\ CloseErrMgr
33
Procedure CloseErrMgr;
Ideally a CloseErrMgr should be done at the end of execution to make sure all files opened by the ErrMgr are closed.
You can let normal program termination do the closing. But if you are a purist...
Get the error message text corresponding to tool error number errNbr from the tool error message file (whose name was specified in the InitErrMgr call). The text of the message is returned in errMsg and the function returns a pointer to errMsg. The maximum length of the message is limited to 254 characters. If the message is to have an insert, then ErrInsert should be a pointer to it. Otherwise it should be either be a null string or a NULL pointer.
Inserts are indicated in error messages by specifying a '^' to indicate where the insert is to be placed.
Note, if a tool message filename was not specified to InitErrMgr, then the ErrMgr assumes the message file contained in the data fork of the tool calling the ErrMgr. This name is contained in the Shell variable {Command} and the value of that variable is used to open the error message file. *)
Get the error message text corresponding to system error number errNbr from the system error message file (whose name was specified in the InitErrMgr call). The text of the message is returned in errMsg and the function returns a pointer to errMsg. The maximum length of the message is limited to 254 characters.
Note, if a system message filename was not specified to InitErrMgr, then the ErrMgr assumes the message file contained in the file "SysErrs.Err". This file is first accessed as "{ShellDirectory}SysErrs.Err" on the assumption that SysErrs.Err is kept in the same directory as the MPW Shell. If the file cannot be opened, then an open is attempted on "SysErrs.Err" in the System Folder.
Add another insert to an error message string.This call is used when more than one insert is to be added to a message (because it contains more than one '^' character).\ InitGrf3D
InitPalettes initializes the Palette Manager. It searches for devices which support a Color Look-Up Table (CLUT) and initializes an internal data structure for each one. This call is made by InitWindows and should not have to be made by your application.
NewPalette allocates a new Palette object which contains a table of colors with enough room for “entries” colors. It fills the table with as many RGB values from srcColors as it has or as it can fit. It sets the usage field of each color to srcUsage and the tolerance value of each color to srcTolerance. If no color table is provided (srcColors = NIL) then all colors in the palette are set to black (red = $0000, green = $0000, blue = $0000 ).
\ GetNewPalette
37
Function GetNewPalette (paletteID: INTEGER) : PaletteHandle;
GetNewPalette fetches a Palette object from the Resource Manager and initializes it. If you open a new color window with GetNewCWindow, this routine is called automatically with paletteID equal to the window’s resource ID. A palette resource is identified by type 'pltt'. A paletteID of 0 is reserved for the system palette resource which is used as the default palette for noncolor windows and color windows without assigned palettes.
DisposePalette disposes of a Palette object. If the palette has any entries allocated for animation on any display device, these entries are relinquished prior to deallocation of the object.
\ ActivatePalette
37
Procedure ActivatePalette (srcWindow: WindowPtr);
ActivatePalette is the routine called by the Window Manager when your window’s status changes: for example, when it opens, closes, moves, or becomes frontmost. You should call ActivatePalette after making changes to a palette with the utility routines described below. Such changes do not take effect until the next call to ActivatePalette, thereby allowing you to make a series of palette changes without any immediate change in the color environment.
If srcWindow is frontmost, ActivatePalette examines the information stored in the palette associated with srcWindow and attempts to provide the color environment described therein. It determines a list of devices on which to render the palette by intersecting the port rect of the srcWindow with each device. If the intersection is not empty, and if the device has a Color Look-Up Table (CLUT), then ActivatePalette checks to see if the color environment is sufficient. If a change is required, ActivatePalette calls the Color Manager to reserve or modify the device’s color entries as required. It then generates update events for all affected windows which desire color updates.
SetPalette changes the palette associated with dstWindow to srcPalette. It also records whether the window wants to receive updates as a result of a change to its color environment. If you want dstWindow to be updated whenever its color environment changes, set cUpdates to TRUE.
\ GetPalette
37
Function GetPalette (srcWindow: WindowPtr) : PaletteHandle;
GetPalette returns a handle to the palette associated with srcWindow. If no palette is associated with srcWindow, or if srcWindow is not a color window, GetPalette returns NIL.
\ PmForeColor
37
Procedure PmForeColor (dstEntry: INTEGER);
PmForeColor sets the RGB and index forecolor fields of the current cGrafPort according to the palette entry of the current cGrafPort (window) corresponding to dstEntry. For courteous and tolerant entries, this call performs an RGBForeColor using the RGB color of the palette entry. For animating colors it will select the recorded device index previously reserved for animation (if still present) and install it in the cGrafPort. The RGB forecolor field is set to the value from the palette entry. For explicit colors PmForeColor places (dstEntry modulo (MaxIndex+1)) into the cGrafPort, where MaxIndex is the largest index available in a device’s CLUT. When multiple devices are present with different depths, MaxIndex varies appropriately for each device.
\ PmBackColor
37
Procedure PmBackColor (dstEntry: INTEGER);
PmBackColor sets the RGB and index backcolor fields of the current cGrafPort according to the palette entry of the current cGrafPort (window) corresponding to dstEntry. For courteous and tolerant entries, this call performs an RGBBackColor using the RGB color of the palette entry. For animating colors it will select the recorded device index previously reserved for animation (if still present) and install it in the cGrafPort. The RGB backcolor field is set to the value from the palette entry. For explicit colors PmBackColor places (dstEntry modulo (MaxIndex+1)) into the cGrafPort, where MaxIndex is the largest index available in a device’s color table. When multiple devices are present with different depths, MaxIndex varies appropriately for each device.
AnimateEntry changes the RGB value of dstEntry in the palette associated with dstWindow to the color specified by srcRGB. Each device for which an index has been reserved is immediately modified to contain the new value. This is not considered to be a change to the device’s color environment since no other windows should be using the animated entry. If the palette entry is not an animating color, or if the associated indexes are no longer reserved, no animation is performed.
If you have blocked color updates in a window, by using SetPalette with CUpdates set to FALSE, you may observe undesired animation. This will occur when ActivatePalette reserves device indexes for animation which are already used in the window. Redrawing the window, which normally occurs as the result of a color update event, will remove any animating colors which do not belong to it.
AnimatePalette performs a function similar to AnimateEntry, but it acts upon a range of palette entries. Beginning at srcIndex (which has a minimum value of 0), the next dstLength entries are copied from srcCTab to dstWindow’s palette, beginning at dstEntry. If srcCTab is not sufficiently large to accommodate the request, as many entries are modified as possible and the remaining entries are left unchanged.
\ GetEntryColor
37
Procedure GetEntryColor (srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstRGB: RGBColor);
GetEntryColor allows your application to access the color of a palette entry. The color may be modified by using the SetEntryColor routine described below.
SetEntryColor provides a convenient way for your application to modify the color of a single palette entry. When you perform a SetPaletteEntry, the entry is marked as having changed, but no change occurs in the color environment. The change will be effected upon the next call to ActivatePalette. Modified entries are marked such that the palette will be updated even though no update might be required by a change in the color environment.
\ GetEntryUsage
37
Procedure GetEntryUsage (srcPalette: PaletteHandle; srcEntry: INTEGER; VAR dstUsage,dstTolerance: INTEGER);
GetEntryUsage allows your application to access the usage fields of a palette entry, namely ciUsage and ciTolerance. These fields may be modified by using the SetEntryUsage routine described below.
SetEntryUsage provides a convenient way for your application to modify the color of a single palette entry. When you perform a SetEntryUsage, the entry is marked as having changed, but no change occurs in the color environment. The change will be effected upon the next call to ActivatePalette. Modified entries are marked such that the palette will be updated even though no update might be required by a change in the color environment. If either myUsage or myTolerance are set to $FFFF (–1) they will not be changed.
This call is provided to allow easy modifications to a palette created with NewPalette or modified by CTab2Palette. In such cases the ciUsage and ciTolerance fields are homogeneous since only one value can be designated for each. You will typically call SetEntryUsage after those calls in order to adjust and customize your palette.
CTab2Palette is a convenience procedure which copies the fields from an existing ColorTable record into an existing Palette record. If the records are not the same size then the Palette record is resized to match the number of entries in the ColorTable record. If dstPalette has any entries allocated for animation on any display device, these entries are relinquished prior to copying the new colors. If you wish to effect color table animation you can change the colors in a palette, and on corresponding devices, with the AnimateEntry and AnimatePalette routines described above. Changes made to a palette by CTab2Palette don’t take effect until the next ActivatePalette is performed. If either the color table handle or the palette handle are NIL, no operation is performed.
Palette2CTab is a convenience procedure which copies all of the colors from an existing Palette record into an existing ColorTable record. If the records are not the same size then the ColorTable record is resized to match the number of entries in the Palette record. If either the palette handle or the color table handle are NIL, no operation is performed.
\ InitPerf
38
Function InitPerf (VAR thePerfGlobals: TP2PerfGlobals;
if InitPerf succeeds then TermPerf must be called before terminating program.
\ PerfControl
38
Function PerfControl (thePerfGlobals: TP2PerfGlobals;
turnOn: BOOLEAN): BOOLEAN;
Call this this to turn on/off performance measure.
Returns previous state.
\ PerfDump
38
Function PerfDump (thePerfGlobals: TP2PerfGlobals;
reportFile: Str255; doHistogram:BOOLEAN;
rptFileColumns: INTEGER Number of columns in the report file}
): INTEGEROSErr};
Call this to dump the performance statistics into a file.
\ CvtPC
38
Function CvtPC (thePerfGlobals: TP2PerfGlobals; pc: LONGINT): LONGINT;
\ GetColor
39
Function GetColor(where: Point; prompt: Str255; inColor: RGBColor; VAR outColor: RGBColor) : BOOLEAN;
GetColor displays the Color Picker dialog box on the screen, with its top-left corner located at where. (The where Point should be on the main gDevice.) If where = (0,0), the dialog box is positioned neatly on the screen, centered horizontally, and with one third of the empty space above the box, two thirds below, whatever the screen size.
The prompt string is displayed in the upper-left corner of the dialog box. InColor is the starting color, which the user may want for comparison, and is displayed immediately below the current output color (the one the user is picking). OutColor is set to the last color value the user picked, if and only if the user clicks OK. On entry, it is treated as undefined, so the output color sample originally matches the input. While the color being picked may vary widely, the input color sample remains fixed, and clicking in the input sample resets the output color sample to match it.
GetColor returns TRUE if the user exits via the OK button, or FALSE if the user cancels.
Assembly-language note: the trap macro for the Color Picker Package is _Pack12. The routine selectors are as follows:
Fix2SmallFract EQU 1
SmallFract2Fix EQU 2
CMY2RGB EQU 3
RGB2CMY EQU 4
HSL2RGB EQU 5
RGB2HSL EQU 6
HSV2RGB EQU 7
RGB2HSV EQU 8
GetColor EQU 9
\ CMY2RGB
39
Procedure CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
\ RGB2CMY
39
Procedure RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
\ HSL2RGB
39
Procedure HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
\ RGB2HSL
39
Procedure RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
\ HSV2RGB
39
Procedure HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
\ RGB2HSV
39
Procedure RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
\ Fix2SmallFract
39
Function Fix2SmallFract(f: Fixed): SmallFract;
A SmallFract can represent a value between 0 and 65,535. They can be assigned directly to and from INTEGERs.
\ SmallFract2Fix
39
Function SmallFract2Fix(s: SmallFract): Fixed;
A SmallFract can represent a value between 0 and 65,535. They can be assigned directly to and from INTEGERs.
\ IEEEDefaultEnv
40
Function IEEEDefaultEnv: Environment;
\ GetTrapVector
40
Procedure GetTrapVector(VAR Traps: TrapVector);
\ SetTrapVector
40
Procedure SetTrapVector(Traps: TrapVector);
\ X96toX80
40
Function X96toX80(x: EXTENDED): Extended80;
\ X80toX96
40
Function X80toX96(x: Extended80): EXTENDED;
\ Sin
40
Function Sin(x: EXTENDED): EXTENDED;
\ Cos
40
Function Cos(x: EXTENDED): EXTENDED;
\ ArcTan
40
Function ArcTan(x: EXTENDED): EXTENDED;
\ Exp
40
Function Exp(x: EXTENDED): EXTENDED;
\ Ln
40
Function Ln(x: EXTENDED): EXTENDED;
\ Log2
40
Function Log2(x: EXTENDED): EXTENDED;
\ Ln1
40
Function Ln1(x: EXTENDED): EXTENDED;
\ Exp2
40
Function Exp2(x: EXTENDED): EXTENDED;
\ Exp1
40
Function Exp1(x: EXTENDED): EXTENDED;
\ Tan
40
Function Tan(x: EXTENDED): EXTENDED;
\ GetHaltVector
40
Function GetHaltVector: LONGINT;
\ SetHaltVector
40
Procedure SetHaltVector(v: LONGINT);
\ X96toX80
40
Function X96toX80(x: Extended96): EXTENDED;
\ X80toX96
40
Function X80toX96(x: EXTENDED): Extended96;
\ Log2
40
Function Log2(x: EXTENDED): EXTENDED;
\ Ln1
40
Function Ln1(x: EXTENDED): EXTENDED;
\ Exp2
40
Function Exp2(x: EXTENDED): EXTENDED;
\ Exp1
40
Function Exp1(x: EXTENDED): EXTENDED;
\ Tan
40
Function Tan(x: EXTENDED): EXTENDED;
\ Num2Integer
40
Function Num2Integer(x: EXTENDED): INTEGER;
\ Num2Longint
40
Function Num2Longint(x: EXTENDED): LONGINT;
\ Num2Real
40
Function Num2Real(x: EXTENDED): real;
\ Num2Double
40
Function Num2Double(x: EXTENDED): DOUBLE;
\ Num2Extended
40
Function Num2Extended(x: EXTENDED): EXTENDED;
\ Num2Comp
40
Function Num2Comp(x: EXTENDED): comp;
\ Num2Dec
40
Procedure Num2Dec(f: DecForm; x: EXTENDED; VAR d: Decimal);
\ Dec2Num
40
Function Dec2Num(d: Decimal): EXTENDED;
\ Num2Str
40
Procedure Num2Str(f: DecForm; x: EXTENDED; VAR s: DecStr);
\ Str2Num
40
Function Str2Num(s: DecStr): EXTENDED;
\ Str2Dec
40
Procedure Str2Dec(s: DecStr; VAR Index: INTEGER; VAR d: Decimal;
VAR ValidPrefix: BOOLEAN);
\ CStr2Dec
40
Procedure CStr2Dec(s: CStrPtr; VAR Index: INTEGER; VAR d: Decimal;
VAR ValidPrefix: BOOLEAN);
\ Dec2Str
40
Procedure Dec2Str(f: DecForm; d: Decimal; VAR s: DecStr);
\ Remainder
40
Function Remainder(x, y: EXTENDED; VAR quo: INTEGER): EXTENDED;
\ Rint
40
Function Rint(x: EXTENDED): EXTENDED;
\ Scalb
40
Function Scalb(n: INTEGER; x: EXTENDED): EXTENDED;
\ Logb
40
Function Logb(x: EXTENDED): EXTENDED;
\ CopySign
40
Function CopySign(x, y: EXTENDED): EXTENDED;
\ NextReal
40
Function NextReal(x, y: real): real;
\ NextDouble
40
Function NextDouble(x, y: DOUBLE): DOUBLE;
\ NextExtended
40
Function NextExtended(x, y: EXTENDED): EXTENDED;
\ XpwrI
40
Function XpwrI(x: EXTENDED; i: INTEGER): EXTENDED;
\ XpwrY
40
Function XpwrY(x, y: EXTENDED): EXTENDED;
\ Compound
40
Function Compound(r, n: EXTENDED): EXTENDED;
\ Annuity
40
Function Annuity(r, n: EXTENDED): EXTENDED;
\ RandomX
40
Function RandomX(VAR x: EXTENDED): EXTENDED;
\ ClassReal
40
Function ClassReal(x: real): NumClass;
\ ClassDouble
40
Function ClassDouble(x: DOUBLE): NumClass;
\ ClassComp
40
Function ClassComp(x: comp): NumClass;
\ ClassExtended
40
Function ClassExtended(x: EXTENDED): NumClass;
\ SignNum
40
Function SignNum(x: EXTENDED): INTEGER;
\ NAN
40
Function NAN(i: INTEGER): EXTENDED;
\ SetException
40
Procedure SetException(e: Exception; b: BOOLEAN);
\ TestException
40
Function TestException(e: Exception): BOOLEAN;
\ SetHalt
40
Procedure SetHalt(e: Exception; b: BOOLEAN);
\ TestHalt
40
Function TestHalt(e: Exception): BOOLEAN;
\ SetRound
40
Procedure SetRound(r: RoundDir);
\ GetRound
40
Function GetRound: RoundDir;
\ SetPrecision
40
Procedure SetPrecision(p: RoundPre);
\ GetPrecision
40
Function GetPrecision: RoundPre;
\ SetEnvironment
40
Procedure SetEnvironment(e: Environment);
\ GetEnvironment
40
Procedure GetEnvironment(VAR e: Environment);
\ ProcEntry
40
Procedure ProcEntry(VAR e: Environment);
\ ProcExit
40
Procedure ProcExit(e: Environment);
\ Relation
40
Function Relation(x, y: EXTENDED): RelOp;
\ SCSIReset
34
Function SCSIReset: OSErr;
\ SCSIGet
34
Function SCSIGet: OSErr;
\ SCSISelect
34
Function SCSISelect(targetID: INTEGER): OSErr;
\ SCSICmd
34
Function SCSICmd(buffer: Ptr; count: INTEGER): OSErr;
\ SCSIRead
34
Function SCSIRead(tibPtr: Ptr): OSErr;
\ SCSIRBlind
34
Function SCSIRBlind(tibPtr: Ptr): OSErr;
\ SCSIWrite
34
Function SCSIWrite(tibPtr: Ptr): OSErr;
\ SCSIWBlind
34
Function SCSIWBlind(tibPtr: Ptr): OSErr;
\ SCSIComplete
34
Function SCSIComplete(VAR stat, message: INTEGER; wait: LONGINT): OSErr;
\ SCSIStat
34
Function SCSIStat: INTEGER;
\ SCSISelAtn
34
Function SCSISelAtn(targetID: INTEGER): OSErr;
SCSISelAtn is identical in function to SCSISelect except that it asserts the Attention line during selection, signaling that you want to send a message to the device.
\ SCSIMsgIn
34
Function SCSIMsgIn(VAR message: INTEGER): OSErr;
\ SCSIMsgOut
34
Function SCSIMsgOut(message: INTEGER): OSErr;
\ IEsigset
41
Function IEsigset(sgMap: SignalMap; sigHdlr: UNIV SignalHandler):
Function GetCVariant (theControl: ControlHandle) : INTEGER; [Macintosh Plus, Macintosh SE, and Macintosh II]
The GetVariant function returns the variant control value for the control described by theControl. This value was formerly stored in the high four bits of the control defproc handle; for future compatibility, use the GetCVariant routine to access this value.
The SetCtlColor procedure sets or modifies a control’s color table. If the control currently has no auxiliary control record, a new one is created with the given color table and added to the head of the auxiliary control list. If there is already an auxiliary record for the control, its color table is replaced by the contents of newColorTable.
If newColorTable has the same contents as the default color table, the control’s existing auxiliary record and color table are removed from the auxiliary control list and deallocated. If theControl = NIL, the operation modifies the default color table itself. If the control is visible, it will be redrawn by SetCtlColor using the new color table.
\ GetAuxCtl
6
Function GetAuxCtl (theControl: ControlHandle; VAR acHndl: AuxCtlHndl) : BOOLEAN; [Macintosh II]
The GetAuxCtl function returns a handle to a control’s color table:
- If the given control has its own color table, the function returns TRUE.
- If the control used the default color set, the function returns FALSE.
- If the control asked to receive the default color set (theControl = NIL), then the function returns TRUE.
\ cdev
43
Function cdev(message, Item, numItems, CPanelID: INTEGER;
VAR theEvent: EventRecord; cdevValue: LONGINT;
CPDialog: DialogPtr) : LONGINT;
Field descriptions
message A message number, from the list defined below, that allows the Control Panel to tell the cdev what event has just taken place.
Item For hitDev messages only: the dialog item number of the item that was hit. Since the cdev’s DITL is appended to the Control Panel’s DITL, the number of items preceding the cdev’s must be subtracted to get a value that is meaningful to the cdev. (See the hitDev message, described below.)
numItems The number of items in the DITL, belonging to the Control Panel, that precede the cdev’s dialog items in the item list.
CPanelID The base resource ID of the Control Panel driver. This value is private to the Control Panel.
theEvent For hit, null, activate, deactivate, and key events: the event record for the event that caused the message. See the Toolbox Event Manager in Volume I for details of the EventRecord structure.
cdevValue The value the cdev returned the last time it was called by the Control Panel, or a return message from the Control Panel. When a cdev is initialized it typically allocates some storage for state information or other data it needs to run. Since desk accessories in general and the Control Panel in particular—and therefore cdevs—cannot have global variables, the cdevValue, which is passed to the cdev for every message, is often used for storing data. The cdevValue is also used by the Control Panel to communicate error handling action to the cdev. See “Storage in a Cdev” and “Cdev Error Checking” later in this chapter.
CPDialog The Control Panel DialogPtr. This may be a color dialog on Macintoshes that support color windows.
The function value returned will be one of three kinds. The Control Panel’s initial call to a cdev will be a macDev call, described below. The cdev responds with a function value that tells the Control Panel whether the cdev should be displayed or not. In subsequent calls the cdev function result may be an error code, or data that needs to be kept until the Control Panel’s next call. The function result is generally passed back to the cdev in the cdevValue parameter at the next cdev function call.
The cdev will be called with the current resource file set to the cdev file, the current grafPort set to the Control Panel’s dialog, and the default volume set to the System Folder of the current startup disk. The cdev must preserve all of these. Also note that the Control Panel sets the cursor to the cross cursor whenever it is above the cdev area of the Control Panel window. Your cdev thus has control of the cursor only during the call; if you change it, the Control Panel will immediately reset it.
Your cdev may be reentered, especially if you put up dialog or alert boxes. The Dialog Manager calls SystemEvent and SystemTask, which may cause a deactivate message to be sent while your cdev is still processing the previous message.
Messages
The following cdev message values have been defined:
CONST
initDev = 0; {initialization}
hitDev = 1; {user clicked dialog item}
closeDev = 2; {user selected another cdev or CP closed}
nulDev = 3; {desk accessory run}
updateDev = 4; {update event}
activDev = 5; {activate event}
deActivDev = 6; {deactivate event}
keyEvtDev = 7; {key-down or auto-key event}
macDev = 8; {check machine characteristics}
undoDev = 9; {standard Edit menu undo}
cutDev =10; {standard Edit menu cut}
copyDev =11; {standard Edit menu copy}
pasteDev =12; {standard Edit menu paste}
clearDev =13; {standard Edit menu clear}
The messages are described below.
Before dispatching to handle a specific message, all cdevs should have some common defensive behavior, for example ensuring that they have enough memory to run. Public-minded cdevs keep a minimum of memory allocated between calls, and memory that was free may be consumed by other applications while Control Panel is inactive, so it is important to check that there is enough memory available on every message.
As part of their memory check, cdevs that depend on various Toolbox packages should ensure that there’s still room to load them. Cdevs should also ignore any messages (except macDev) received before initialization, or after shutdown or an error.
Your cdev, as part of a desk accessory that may move from one invocation to another, cannot use global variables. This in turn means that you cannot set user item procedures for drawing user items in the 'DITL', because the procedure pointers will dangle if the code moves. Instead, you must draw your user items in response to update messages. Also, you must find Quickdraw globals by means of thePort if you need to reference them.
See the sample cdev for examples.
The macDev Message
If the 'mach' resource has a 0 in Softmask and a –1 ($FFFF) in Hardmask, the first message a cdev will get is a macDev message. This is an opportunity for the cdev to determine whether it can run, and whether it should appear in the Control Panel’s cdev list. The cdev can do its own check to see which machine it is being run on, what hardware is connected, and what is in the slots (if it has slots). The cdev must then return a function result of 1 or 0. If a 0 is returned, the Control Panel will not display the cdev in the icon list. (Note that the Control Panel does not interpret this 0 or 1 as an error message as described under “Cdev Error Checking”.)
The macDev call happens only once, and only when Softmask and Hardmask are 0 and FFFF. It is always the first call made to the cdev.
The initDev Message
InitDev is an initialization message sent to allow the cdev to allocate its private storage (if any) and do any initial settings to buttons or controls. This message is sent when the user clicks on the cdev’s icon.
Note that the dialog, cdev list, and all of the items in the cdev’s 'DITL' except user items will already have been drawn when the initDev message is sent.
If your cdev doesn’t need any storage it should return the value that was passed to it in cdevValue.
The activDev Message
An activDev message is sent to the cdev on every activate event. It allows the cdev to reset any items that may have changed while the Control Panel was inactive. It also allows the cdev to send things such as “lists activate” messages.
The updateDev Message
An updateDev message is sent to the cdev on every update event. It allows the cdev to perform any updating necessary aside from the standard dialog item updating provided by the Dialog Manager. For example, if the cdev resource contains a picture of the sound control bar, it will probably be a user item, and the picture of the control bar and the volume knob should be redrawn in response to update events.
Note that there is no mechanism for determining what to update, as the update region has already been reset. You must redraw all of your user items completely.
The nulDev Message
A nulDev message is sent to the cdev on every Control Panel run event. This allows the cdev to perform tasks that need to be executed continuously (insertion point blinking, for example).
A cdev cannot assume any particular timing of calls from applications. Don’t use nulDev to refresh settings; see activDev, above.
The hitDev Message
A hitDev message is sent when the user has clicked an enabled dialog item that belongs to the cdev. The dialog item number of the item hit is passed in the Item parameter. Remember that the Control Panel’s items precede yours, so you’ll want (Item – numItems) to determine which of your items was hit. If the Control Panel itself has n items, the first of the cdev’s items will be n+1 in the combined dialog item list. A cdev should not depend on any hardcoded value for numItems, since the number of items in Control Panel’s 'DITL' is likely to change in the future.
Factoring in numItems need not mean an increase in your code size, or passing and adding numItems everywhere, or foregoing the constants that most developers use to identify specific items. You can do it easily, and neatly, as follows:
1. Subtract numItems from Item right away, and refer to your dialog items with constants as usual throughout the cdev.
2. Write simple envelope routines to enclose Dialog Manager procedures that require item number arguments. Add numItems only locally, within those routines and for the Dialog Manager calls only.
This is demonstrated in the sample cdev.
The keyEvtDev Message
A keyEvtDev message is sent to the cdev on every keyDown event and autoKey event. It allows the cdev to process key events. On return to the Control Panel, the key event will be processed by a call to dialogSelect in the Dialog Manager. A cdev that does not want the Toolbox Event Manager to do any further processing should change the what field of the EventRecord to nullEvent before returning to the Control Panel.
The deActivDev Message
A deActivDev message is sent to the cdev on every deactivate event. It allows the cdev to send deactivate messages to items such as lists.
The closeDev Message
A closeDev message is sent to the cdev when either the Control Panel is closed or the user selects another cdev. When a cdev receives a closeDev message it should dispose of any storage it has allocated, including the handle stored in cdevValue, if any.
The Standard Edit Menu Messages
Values 9 through 13 have been defined in order to provide the standard Edit menu functions of Undo, Cut, Copy, Paste, and Clear for applications that need to implement them.
STORAGE IN A CDEV
Since normal global storage is not available, the Control Panel, like all desk accessories, uses a special mechanism to store values between calls. The cdevValue parameter in the cdev call extends this storage mechanism to cdevs.
If a cdev needs to store information between calls it should create a handle during the initDev call, and return it as the cdev function result. The Control Panel always returns such handles in the cdevValue parameter at the next call.
If the cdev is called with a closeDev message, or if it needs to shut down because of an error, then this handle and any pointers or handles within the storage area should be disposed of before returning to the Control Panel.
CDEV ERROR CHECKING
Because a desk accessory may be called into many strange and wonderful situations, careful attention must be paid to error checking. The two most common error conditions are missing resources and lack of memory. Some error reporting and recovery facilities have been provided in the Control Panel to help with errors encountered in a cdev.
Because the Control Panel has no direct information about the cdev, the cdev’s code must be able to detect and recover from error conditions on its own. If the recovery cannot be effected the cdev must dispose of any memory it has allocated, and exit back to the Control Panel with an error code.
Following a shutdown, the Control Panel can help report the error condition to the user and prevent accidental reentry into the cdev that might result from such things as an update event. A cdev can request three different error reporting mechanisms from the Control Panel:
- If a memory error has occured, then, after the cdev has safely shut itself down, it may request the Control Panel to issue an out-of-memory error message and gray out (paint over with the background pattern) the cdev area of the Control Panel window. It will remain grayed until another cdev is selected. The Control Panel window itself is not closed since other cdevs may still be able to function in the environment.
- If a resource error is detected, the cdev may request that a can’t-find-needed-resource error message be issued.
- The cdev may display its own error message and then call on the Control Panel to gray its area.
The Control Panel uses the cdevValue parameter to send status information to the cdev, and a proper cdev uses its function value to send information back to the Control Panel. In the absence of errors, the same value passes back and forth: the Control Panel puts the last function value it received into cdevValue when it calls the cdev; the cdev returns the value it finds there as the function value. The cdev may want to keep a handle to its own storage, in which case passing it as the function value ensures its availability, since the Control Panel will pass it back in cdevValue at the next call.
Four constants have been defined for this cdev/Control Panel communication:
CONST
cdevUnset = 3; {initial value passed in cdevValue}
cdevGenErr = -1; {generic cdev error}
cdevMemErr = 0; {insufficient memory for cdev execution}
cdevResErr = 1; {missing resource needed by cdev}
After the macDev call, the Control Panel sends cdevUnset in cdevValue, so that until an error occurs or the cdev uses its function value as a handle, cdevUnset is passed back and forth. If the cdev encounters an error, it should dispose of all handles and pointers it has set up, strip the stack back to the same position as a normal exit, and return one of the three error codes as the function result. The Control Panel will respond as follows:
The cdev code should check cdevValue at entry. A 0 means that the Control Panel has responded to a cdev error message by shutting down the cdev and displaying an error dialog if one was requested. The cdev should immediately exit.
Once the Control Panel has responded to an error message from a cdev it will no longer respond to any return values until another cdev is launched.
\ Sample
43
UNIT cdev;
INTERFACE
USES
MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf;
Function Sample (message, item, numItems, CPanelID: INTEGER;
theEvent: EventRecord; cdevValue: LONGINT;
CPDialog: DialogPtr) : LONGINT;
IMPLEMENTATION
CONST
{ Constants for all of Sample's dialog items }
iVersion = 1; {cdev's version number is just }
{ staticText}
iTitle = 2; {title for Sample is just }
{ staticText}
iShowCounts = 3; {show the events handled/ignored}
iHideCounts = 4; {hide the events handled/ignored}
iTitleHandled = 5; {title for events handled count}
iTitleIgnored = 6; {title for events ignored count}
iHandled = 7; {user item for number of events }
{ handled}
iIgnored = 8; {user item for number of events }
{ ignored}
TYPE
SampleStorage = RECORD
dlgPtr: DialogPtr;
dlgItems: INTEGER;
countShown: BOOLEAN;
msgHandled: INTEGER;
msgIgnored: INTEGER;
END;
SamplePtr = ^SampleStorage;
SampleHdl = ^SamplePtr;
Function InitSample (CPDialog: DialogPtr;
numItems: INTEGER): LONGINT; FORWARD;
Function EnoughRoomToRun (VAR cdevValue: LONGINT) : BOOLEAN; FORWARD;
Function PBHGetVolParms (paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _GetVolParms
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long volume name specifier
——> 22 ioVRefNum word volume refNum
<—— 32 ioBuffer long ptr to vol parms data
——> 36 ioReqCount long size of buffer area
<—— 40 ioActCount long length of vol parms data
The PBHGetVolParms call is used to return volume level information. ioVRefNum or ioFileName contain the volume identifier information. ioReqCount and ioBuffer contain the size and location of the buffer in which to place the volume parameters. The actual size of the information is returned in ioActCount.
The format of the buffer is described below. Version 01 of the buffer is shown below along with offsets into the buffer and their equates:
offset 0 vMVersion word version number (currently 01)
2 vMAttrib long attributes (detailed below)
6 vMLocalHand long handle used to keep information necessary
for shared volumes
10 vMServerAdr long AppleTalk server address (0 if not
supported)
On creation of the VCB (right after mounting), vMLocalHand will be a handle to a 2 byte block of memory. The Finder uses this for its local window list storage, allocating and deallocating memory as needed. It is disposed of when the volume is unmounted.
For AppleTalk server volumes, vMServerAdr contains the AppleTalk internet address of the server. This can be used to tell which volumes are for which server.
vMAttrib contains attributes information (32 flag bits) about the volume. These bits and their equates are defined as follows:
bit 31 bLimitFCBs If set, Finder limits the number of FCBs used during
copies to 8 (instead of 16).
30 bLocalWList If set, Finder uses the returned shared volume handle
for its local window list.
29 bNoMiniFndr If set, Mini Finder menu item is disabled.
28 bNoVNEdit If set, volume name cannot be edited.
27 bNoLclSync If set, volume’s modification date is not set by any
Finder action.
\ PBHGetLogInInfo
17
Function PBHGetLogInInfo (paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _GetLogInInfo
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 22 ioVRefNum word volume refNum
<—— 26 ioObjType word log in method
<—— 28 ioObjNamePtr long ptr to log in name buffer
PBHGetLogInInfo returns the method used for log-in and the user name specified at log-in time for the volume. The log-in user name is returned as a Pascal string in ioObjNamePtr. The maximum size of the user name is 31 characters. The log-in method type is returned in ioObjType.
\ PBHGetDirAccess
17
Function PBHGetDirAccess (paramBlock: HParmBlkPtr; async: BOOLEAN): OSErr;
Trap macro _GetDirAccess
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long directory name
——> 22 ioVRefNum word volume refNum
<—— 36 ioACOwnerID long owner ID
<—— 40 ioACGroupID long group ID
<—— 44 ioACAccess long access rights
——> 48 ioDirID long directory ID
PBHGetDirAccess returns access control information for the folder pointed to by the ioDirID/ioFIleName pair. ioACOwnerID will return the ID for the folder’s owner. ioACGroupID will return the ID for the folder’s primary group. The access rights are returned in ioACAccess.
A fnfErr is returned if the pathname does not point to a valid directory. An AccessDenied error is returned if the user does not have the correct access rights to examine this directory.
\ PBHSetDirAccess
17
Function PBHSetDirAccess (paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _SetDirAccess
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long pathname identifier
——> 22 ioVRefNum word volume refNum
——> 36 ioACOwnerID long owner ID
——> 40 ioACGroupID long group ID
——> 44 ioACAccess long access rights
——> 48 ioDirID long directory ID
PBHSetDirAccess allows you to change the access rights to a folder pointed to by the ioFileName/ioDirID pair. IOACOwnerID contains the new owner ID. IOACGroupID contains the group ID. IOACAccess contains the folder’s access rights. You cannot set the owner bit or the user’s rights of the directory. To change the owner or group, you should set the ioACOwnerID or ioACGroupID field with the appropriate ID of the new owner/group. You must be the owner of the directory to change the owner or group ID.
A fnfErr is returned if the pathname does not point to a valid directory. An AccessDenied error is returned if you do not have the correct access rights to modify the parameters for this directory. A paramErr is returned if you try to set the owner bit or user’s rights bits.
\ PBHMapID
17
Function PBHMapID (paramBlock: HParmBlkPtr; async: BOOLEAN): OSErr;
Trap macro _MapID
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long pathname identifier
——> 22 ioVRefNum word volume refNum
——> 26 ioObjType word function code
<—— 28 ioObjNamePtr long ptr to retrnd creator/group name
——> 32 ioObjID long creator/group ID
PBHMapID returns the name of a user or group given its unique ID. IOObjID contains the ID to be mapped. The value zero for ioObjID is special cased and will always return a NIL name. AppleShare uses this to signify <Any User>. IOObjType is the mapping function code; it’s 1 if you’re mapping an owner ID to owner name or 2 if you’re mapping a group ID to a group name. The name is returned as a Pascal string in ioObjNamePtr. The maximum size of the name is 31 characters.
A fnfErr is returned if an unrecognizable owner or group ID is passed.
\ PBHMapName
17
Function PBHMapName(paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _MapName
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long volume identifier (may be NIL)
——> 22 ioVRefNum word volume refNum
——> 28 ioObjNamePtr long owner or group name
——> 26 ioObjType word function code
<—— 32 ioObjID long creator/group ID
PBHMapName returns the unique user ID or group ID given its name. The name is passed as a string in ioObjNamePtr. If a NIL name is passed, the ID returned will always be zero. The maximum size of the name is 31 characters. IOObjType is the mapping function code; it’s 3 if you’re mapping an owner name to owner ID or 4 if you’re mapping a group name to a group ID. IOObjID will contain the mapped ID.
A fnfErr is returned if an unrecognizable owner or group name is passed.
\ PBHCopyFile
17
Function PBHCopyFile (paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _CopyFile
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long ptr to source pathname
——> 22 ioVRefNum word source vol identifier
——> 24 ioDstVRefNum word destination vol identifier
——> 28 ioNewName long ptr to destination pathname
——> 32 ioCopyName long ptr to optional name (may be NIL)
——> 36 ioNewDirID long destination directory ID
——> 48 ioDirID long source directory ID
PBHCopyFile duplicates a file on the volume and optionally renames it. It is an optional call for AppleShare file servers. You should examine the returned flag information in the PBHGetVolParms call to see if this volume supports CopyFile.
For AppleShare file servers, the source and destination pathnames must indicate the same file server; however, it may point to a different volume for that file server. A useful way to tell if two file server volumes are on the same file server is to make the GetVolParms call and compare the server addresses returned. The server will open source files with read/deny write enabled and destination files with write/deny read and write enabled.
IOVRefNum contains a source volume identifier. The source pathname is determined by the ioFileName/ioDirID pair. IODstVRefNum contains a destination volume identifier. AppleShare 1.0 required that it be an actual volume reference number; however, on future versions it can be a WDRefNum. The destination pathname is determined by the ioNewName/ioNewDirID pair. IOCopyName may contain an optional string used in renaming the file. If it is non-NIL then the file copy will be renamed to the specified name in ioCopyName.
A fnfErr is returned if the source pathname does not point to an existing file or the destination pathname does not point to an existing directory. An AccessDenied error is returned if the user does not have the right to read the source or write to the destination. A dupFnErr is returned if the destination already exists. A DenyConflict error is returned if either the source or destination file could not be opened under the access modes described above.
\ PBHMoveRename
17
Function PBHMoveRename (paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _MoveRename
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long ptr to source pathname
——> 22 ioVRefNum word source vol identifier
——> 28 ioNewName long ptr to destination pathname
——> 32 ioBuffer long ptr to optional name (may be NIL)
——> 36 ioNewDirID long destination directory ID
——> 48 ioDirID long source directory ID
PBHMoveRename allows you to move (not copy) an item and optionally to rename it. The source and destination pathnames must point to the same file server volume.
IOVRefNum contains a source volume identifier. The source pathname is specified by the ioFileName/ioDirID pair. The destination pathname is specified by the ioNewName/
ioNewDirID pair. IOBuffer may contain an optional string used in renaming the item. If it is non-NIL then the moved object will be renamed to the specified name in ioBuffer.
A fnfErr is returned if the source pathname does not point to an existing object. An AccessDenied error is returned if the user does not have the right to move the object. A dupFnErr is returned if the destination already exists. A badMovErr is returned if an attempt is made to move a directory into one of its descendent directories.
\ PBHOpenDeny
17
Function PBHOpenDeny (paramBlock: HParmBlkPtr; async: BOOLEAN): OSErr;
Trap macro _OpenDeny
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long ptr to pathname
——> 22 ioVRefNum word vol identifier
<—— 24 ioRefNum word file refNum
——> 26 ioDenyModes word access rights data
——> 48 ioDirID long directory ID
PBHOpenDeny opens a file’s data fork under specific access rights. It creates an access path to the file having the name pointed to by ioFileName/ioDirID. The path reference number is returned in ioRefNum.
IODenyModes contains a word of access rights information. The format for these access rights is:
bits 15–6 Reserved—should be cleared.
5 If set, other writers are denied access.
4 If set, other readers are denied access.
3–2 Reserved—should be cleared.
1 If set, write permission requested.
0 If set, read permission requested.
A fnfErr is returned if the input specification does not point to an existing file. A permErr is returned if the file is already open and you cannot open it under the deny modes that you have specified. An opWrErr is returned if you have asked for write permission and the file is already opened by you for write. The already opened path reference number is returned in ioRefNum. An AccessDenied error is returned if you do not have the right to access the file.
\ PBHOpenRFDeny
17
Function PBHOpenRFDeny (paramBlock: HParmBlkPtr; async: BOOLEAN) : OSErr;
Trap macro _OpenRFDeny
Parameter block
——> 12 ioCompletion long optional completion routine ptr
<—— 16 ioResult word error result code
——> 18 ioFileName long ptr to pathname
——> 22 ioVRefNum word vol identifier
<—— 24 ioRefNum word file refNum
——> 26 ioDenyModes word access rights data
——> 48 ioDirID long directory ID
PBHOpenRFDeny opens a file’s resource fork under specific access rights. It creates an access path to the file having the name pointed to by ioFileName/ioDirID. The path reference number is returned in ioRefNum. The format of the access rights data contained in ioDenyModes is described under the OpenDeny call.
A fnfErr is returned if the input specification does not point to an existing file. A permErr is returned if the file is already open and you cannot open it under the deny modes that you have specified. An opWrErr is returned if you have asked for write permission and the file is already opened by you for write. The already-opened path reference number is returned in ioRefNum. An AccessDenied error is returned if you do not have the right to access the file.
\ GetMMUMode
25
Function GetMMUMode (VAR mode: INTEGER);
GetMMUMode returns the address translation mode currently in use.
Assembly-language note: Assembly-language programmers can determine the current address mode by testing the contents of the global variable MMU32Bit; it’s TRUE if 32-bit mode is in effect.
\ SwapMMUMode
25
Procedure SwapMMUMode (VAR mode: Byte);
Trap macro _SwapMMUMode
On entry D0: mode (byte)
On exit D0: mode (byte)
SwapMMUMode sets the address translation mode to that specified by the mode parameter. The mode in use prior to the call is returned in mode, and can be restored with another call to SwapMMUMode.
\ StripAddress
25
Function StripAddress (theAddress: LONGINT) : LONGINT;
Trap macro _StripAddress
On entry D0: theAddress (long word)
On exit D0: function result (long word)
If the system is running in 24-bit addressing mode, StripAddress is identical in function to the global variable Lo3Bytes: it returns the value of the low-order three bytes of the address passed in theAddress. If the system is in 32-bit mode, however, StripAddress simply passes back the address unchanged.
\ RGetResource
1
Function RGetResource (theType: ResType; theID: INTEGER) : Handle;
RGetResource is identical in function to GetResource except that it looks through the chain of open resource files for the specified resource, and if it doesn’t find it there, it looks in the ROM resources.
Note: With System file version 4.1 or later, RGetResource will also work on the Macintosh Plus.
\ SCSIMsgIn
34
Function SCSIMsgIn (VAR message: INTEGER) : OSErr;
SCSIMsgIn gets a message from the device. The message is contained in the low-order byte of the message parameter; message values are listed in the ANSI documentation for SCSI.
SCSIMsgIn leaves the Attention line undisturbed if it’s already asserted upon entry.
\ SCSIMsgOut
34
Function SCSIMsgOut (message: INTEGER) : OSErr;
SCSIMsgOut sends a message byte to the target device; message values are listed in the ANSI documentation for SCSI.
\ ShutDwnPower
45
Procedure ShutDwnPower;
ShutDwnPower performs system housekeeping, executes any shutdown procedures you may have installed with ShutDwnInstall, and turns the machine off. (If the machine must be turned off manually, the shutdown alert is presented.)
\ ShutDwnStart
45
Procedure ShutDwnStart;
ShutDwnPower performs system housekeeping, executes any shutdown procedures you may have installed with ShutDwnInstall, and reboots the machine.
Assembly-language note: ShutDwnStart results in the execution of the Reset instruction, followed by a jump to the ROM boot code (the address is the value of the global variable ROMBase + 10).
ShutDwnInstall installs the shutdown procedure pointed to by shutDwnProc. The flags parameter indicates where in the shutdown process to execute your shutdown procedure. The following masks are provided for setting the bits of the flags parameter:
CONST sdOnPowerOff = 1; {call procedure before power off}
sdOnRestart = 2; {call procedure before restart}
sdOnUnmount = 4; {call procedure before unmounting}
sdOnDrivers = 8; {call procedure before closing drivers}
ShutDwnRemove removes the shutdown procedure pointed to by shutDwnProc.
Note: If the procedure was marked for execution at a number of points in the shutdown process (say, for instance, at unmounting, restart, and power off), it will be removed at all points.
\ SRsrcInfo
46
Function SRsrcInfo(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SRsrcInfo
Required Parameters:
<—— spsPointer
<—— spIOReserved
<—— spRefNum
<—— spCategory
<—— spCType
<—— spDrvrSW
<—— spDrvrHW
——> spSlot
——> spId
——> spExtDev
<—— spHWDev
The trap macro SRsrcInfo returns an sResource list pointer (spsPointer), plus the sResource type (category, cType, software, and hardware), driver reference number (spRefNum), and Slot Resource Table ioReserved field (spIOReserved) for the sResource specified by the slot number spSlot, sResource list identification number spId, and external device identifier spExtDev. This call is most often used to return the driver reference number.
\ SNextsRsrc
46
Function SNextsRsrc(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SNextsRsrc
Required Parameters:
<—> spSlot
<—> spId
<—> spExtDev
<—— spsPointer
<—— spRefNum
<—— spIOReserved
<—— spCategory
<—— spCType
<—— spDrvrSW
<—— spDrvrHW
<—— spHWDev
Starting from a given slot number spSlot, sResource list identification number spId, and external device identifier spExtDev, the trap macro SNextsRsrc returns the slot number, sResource list identification number, sResource type (category, cType, software, and hardware), driver reference number (spRefNum), and Slot Resource Table ioReserved field (spIOReserved) for the next sResource. If there are no more sResources, SNextsRsrc returns a nonfatal error status. This routine can be used to determine the set of all sResources in a given slot card or NuBus configuration.
\ SNextTypesRsrc
46
Function SNextTypesRsrc(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SNextTypesRsrc
Required Parameters:
<—> spSlot
<—> spId
<—> spExtDev
——> spTBMask
<—— spsPointer
<—— spRefNum
<—— spIOReserved
<—> spCategory
<—> spCType
<—> spDrvrSW
<—> spDrvrHW
<—> spHWDev
Given an sResource type (category, cType, software, and hardware) and spTBMask, and starting from a given slot number spSlot and sResource list identification number spId, the trap macro SNextTypesRsrc returns the slot number spSlot, sResource list identification number spId, sResource type, driver reference number (spRefNum), and Slot Resource Table ioReserved field (spIOReserved) for the next sResource of that type, as masked. If there are no more sResources of that type, SNextTypesRsrc returns a nonfatal error report.
The spTBMask field lets you mask off specific fields of the sResource type that you don’t care about, by setting any of bits 0–3. Bit 3 masks off the spCategory field; bit 2 the spCType field; bit 1 the spDrvrSW field; and bit 0 the spDrvrHW field.
This procedure behaves the same as sNextsRsrc except that it returns information only about sResources of the specified type.
\ SReadDrvrName
46
Function SReadDrvrName(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadDrvrName
Required Parameters:
——> spSlot
——> spId
——> spResult
Other Parameters Affected:
spSize
spsPointer
The trap macro SReadDrvrName reads the name of the sResource corresponding to the slot number spSlot and sResource list identification number spId, prefixes a period to the value of the cString and converts its type to Str255. It then reads the result into a Pascal string variable declared by the calling program and pointed to by spResult. The final driver name is compatible with the Open routine.
\ SReadByte
46
Function SReadByte(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadByte
Required Parameters:
——> spsPointer
——> spId
<—— spResult
Other Parameters Affected
spOffsetData
spByteLanes
The trap macro SReadByte returns in spResult an 8-bit value identified by spId from the sResource list pointed to by spsPointer. This routine’s low-order byte can return nonfatal error reports.
\ SReadWord
46
Function SReadWord(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadWord
Required Parameters:
——> spsPointer
——> spId
<—— spResult
Other Parameters Affected
spOffsetData
spByteLanes
The trap macro SReadWord returns in the low-order word of spResult a 16-bit value identified by spId from the sResource list pointed to by spsPointer. This routine can return nonfatal error reports.
\ sReadLong
46
Function sReadLong(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadLong
Required Parameters:
——> spsPointer
——> spId
<—— spResult
Other Parameters Affected
spOffsetData
spByteLanes
spSize
The trap macro SReadLong returns in spResult a 32-bit value identified by spId from the sResource list pointed to by spsPointer. This routine can return nonfatal error reports.
\ SGetCString
46
Function SGetCString(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SGetCString
Required Parameters
——> spsPointer
——> spId
<—— spResult
Other Parameters Affected
spOffsetData
spByteLanes
spSize
spFlags
The trap macro SGetCString copies a cString identified by spId from the sResource list pointed to by spsPointer to a buffer pointed to by spResult. Memory for this buffer is automatically allocated by SGetCString.
\ SGetBlock
46
Function SGetBlock(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SGetBlock
Required Parameters:
——> spsPointer
——> spId
<—— spResult
Other Parameters Affected
spOffsetData
spByteLanes
spSize
spFlags
The trap macro SGetBlock copies the sBlock from the sResource list pointed to by spsPointer and identified by spId into a new block and returns a pointer to it in spResult. The pointer in spResult should be disposed of by using the Memory Manager routine DisposPtr.
\ SFindStruct
46
Function SFindStruct(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _ sFindStruct
Required Parameters:
——> spId
<—> spsPointer
Other Parameters Affected
spByteLanes
The trap macro SFindStruct returns a pointer to the data structure defined by spId in the sResource list pointed to by spsPointer.
\ SReadStruct
46
Function SReadStruct(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadStruct
Required Parameters:
——> spsPointer
——> spSize
——> spResult
Other Parameter Affected
spByteLanes
The trap macro sReadStruct copies a structure of size spSize from the sResource list pointed to by spsPointer into a new block allocated by the calling program and pointed to by spResult.
\ SReadInfo
46
Function SReadInfo(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadInfo
Required Parameters
——> spSlot
——> spResult
Other Parameter Affected
spSize
The trap macro SReadInfo reads the sInfo record identified by spSlot into a new record allocated by the calling program and pointed to by spResult. Here is the structure of the sInfo record:
TYPE
SInfoRecPtr = ^SInfoRecord;
SInfoRecord = PACKED RECORD
siDirPtr: Ptr; {pointer to directory}
siInitStatusA: INTEGER; {initialization error}
siInitStatusV: INTEGER; {status returned by vendor init code}
siCPUByteLanes Each bit set signifies a byte lane used (byte)
siTopOfROM x such that Top of ROM = $FsFFFFFx (byte)
siStatusFlags Bit 0 indicates if card has been changed (byte)
siTOConst Timeout constant for bus error (word)
siReserved Reserved—must be 0 (byte)
sInfoRecSize Size of sInfo record
The siDirPtr field of the sInfo record contains a pointer to the sResource directory in the configuration ROM. The siInitStatusA field indicates the result of efforts to initialize the card. A zero value indicates that the card is installed and operational. A non-zero value is the Slot Manager error code indicating why the card could not be used.
The siInitStatusV field contains the value returned by the card's primary initialization code (in the seStatus field of the seBlock). Negative values cause the card to fail initialization. Zero or positive values indicate that the card is operational.
The siState field is used internally to indicate what initialization steps have occurred so far.
The siCPUByteLanes field indicate which byte lanes are used by the card.
The siTopOfROM field gives the last nibble of the address of the actual ByteLanes value in the fHeader record.
The siStatusFlags field gives status information about the slot. Currently only the fCardIsChanged bit has meaning. A value of 1 indicates that the board ID of the installed card did not match the ID saved in parameter RAM—in other words, the card has been changed.
The siTOConstant field contains the number of retries that will be performed when a bus error occurs while accessing the declaration ROM. It defaults to 100, but may be set to another value with the TimeOut field in the board sResource of the card.
The siReserved field is reserved and should have a value of 0.
\ SReadPRAMRec
46
Function SReadPRAMRec(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadPRAMRec
Required Parameters:
——> spSlot
——> spResult
Other Parameter Affected
spSize
The trap macro SReadPRAMRec copies the sPRAM record data for the slot identified by spSlot to a new record allocated by the calling program and pointed to by spResult.
One sPRAM record for each slot resides in the Macintosh II parameter RAM. The sPRAM record is initialized during startup by InitsPRAMRecs, described below under “Advanced Routines”. Here is its structure:
Assembly-language note: The sPRAM record has the following structure in assembly language:
boardID Apple-defined card indentification (word)
vendorUse1 Reserved for vendor use (byte)
vendorUse2 Reserved for vendor use (byte)
vendorUse3 Reserved for vendor use (byte)
vendorUse4 Reserved for vendor use (byte)
vendorUse5 Reserved for vendor use (byte)
vendorUse6 Reserved for vendor use (byte)
If a card is removed from its slot, the corresponding sPRAM record is cleared at the next system startup. If a different card is plugged back into the slot, the corresponding sPRAM record is reinitialized. A flag is set each time an sPRAM record is initialized, to alert the Start Manager.
\ SPutPRAMRec
46
Function SPutPRAMRec(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SPutPRAMRec
Required Parameters:
——> spSlot
——> spsPointer
The trap macro SPutPRAMRec copies the logical data from the block referenced by spsPointer into the sPRAM record for the slot identified by spSlot. This updates the Macintosh PRAM for that slot. The sPRAM record is defined above under SReadPRAMRec. In this record, the field boardId is an Apple-defined field and is protected during execution of SPutPRAMRec.
\ SReadFHeader
46
Function SReadFHeader(spBlkPtr: SpBlockPtr) : OSErr;
Trap macro: _SReadFHeader
Required Parameters:
——> spSlot
——> spResult
Other Parameters Affected
spsPointer
spByteLanes
spSize
spOffsetData
The trap macro SReadFHeader copies the format block data for the slot designated by spSlot to an FHeader record allocated by the calling program and pointed to by spResult. Here is the structure of FHeader:
TYPE
FHeaderRecPtr = ^FHeaderRec;
FHeaderRec = PACKED RECORD
fhDIROffset: LONGINT; {offset to directory}
fhLength: LONGINT; {length of ROM}
fhCRC: LONGINT; {CRC}
fhROMRev: SignedByte; {revision of ROM}
fhFormat: SignedByte; {format - 2}
fhTstPat: LONGINT; {test pattern}
fhReserved: INTEGER; {reserved}
fhByteLanes: SignedByte;{ByteLanes}
END;
Assembly-language note: The FHeader record has the following structure in assembly language:
fhDIROffset Offset to sResource directory (long)
fhLength Length of card’s declaration ROM (long)
fhCRC Declaration ROM checksum (long)
fhROMRev ROM revision number (byte)
fhFormat ROM format number (byte)
fhTstPat Test Pattern (long)
fhReserved Reserved (byte)
fhByteLanes Byte lanes used (byte)
fhSize Size of the FHeader record
The fHeader record exists at the highest address of a card’s declaration ROM, and should therefore be visible at the highest address in the card’s slot space. The Slot Manager uses the fHeader record to verify that a card is installed in the slot, to determine its physical connection to NuBus (which byte lanes are used), and to locate the sResource directory.
The fhDIROffset field of the fHeader record is a self-relative signed 24-bit offset to the sResource directory. The high order byte must be 0, or a card initialization error occurs.
The fhLength field gives the size of the configuration ROM.
The fhCRC field gives the cyclic redundancy check (CRC) value of the declaration ROM. The CRC value itself is taken as zero in the CRC calculation.
The fhRomRev field gives the revision level of this declaration ROM. Values greater than 9 cause a card initialization error.
The fhFormat field identifies the format of the configuration ROM. Only the value 1 (appleFormat ) is currently recognized as valid.
The fhTstPat field is used to verify that the fhByteLanes field is correct.
The fhReserved field must be zero.
The fhByteLanes field indicates what NuBus byte lanes are used by the card. Byte lanes are described in the “Access to Address Space” chapter of Designing Cards and Drivers for Macintosh II and Macintosh SE.
\ SCkCardStatus
46
Function SCkCardStatus(spBlkPtr: SpBlockPtr) : OSErr;
GetDefaultStartup returns information about the default startup device from parameter RAM. To determine which variant to use, you need to look at the sdRefNum field. If this field contains a negative number, it’s the driver reference number for an SCSI device, which is all you need to know. (SDReserved1 and sdReserved2 are reserved for future use.)
If sdRefNum contains a positive number, you’ll need to access the information in the slotDev variant. SDExtDevID is specified by a slot’s driver; it identifies one of perhaps several devices that are connected through a single slot. SDSlotNum is the slot number ($9 thru E) and sdSRsrcID is the sResource ID; see the Slot Manager chapter for details.
SetDefaultStartup specifies a device as the default startup device. For a slot device, sdExtDevID (specified by the slot’s driver) identifies one of perhaps several devices that are connected through a single slot. SDSlotNum is the slot number ($9 thru E) and sdSRsrcID is the sResource ID; see the Slot Manager chapter for details.
In the case of an SCSI device, sdRefNum contains the reference number; to specify no device as default (meaning that the first available device will be chosen at startup), pass 0 in sdRefNum. SDReserved1 and sdReserved2 are reserved for future use and should be 0.
GetVideoDefault returns the slot number and sResourceID of the default video device. If sdSlot returns 0, there is no default video device and the first available video device will be chosen.
SetVideoDefault makes the device with the given slot number and sResourceID the default video device.
\ GetOSDefault
48
Procedure GetOSDefault (paramBlock: DefOSPtr);
Trap macro _GetOSDefault
Parameter block
<—— 0 sdReserved byte
<—— 1 sdOSType byte
GetOSDefault returns a value in sdOSType identifying the operating system to be used at startup. The sdReserved parameter currently returns 0; it’s reserved for future use. This call is generally used only with partitioned devices containing multiple operating systems; for more details, see the SCSI Manager chapter in this volume.
\ SetOSDefault
48
Procedure SetOSDefault (paramBlock: DefOSPtr);
Trap macro _SetOSDefault
Parameter block
——> 0 sdReserved byte
——> 1 sdOSType byte
SetOSDefault specifies in sdOSType the operating system to be used at startup. The sdReserved parameter is reserved for future use and should be 0. This call is generally used only with partitioned devices containing multiple operating systems; for details, see the SCSI Manager chapter in this volume.
\ GetTimeout
48
Procedure GetTimeout (VAR count: INTEGER);
Trap macro _GetTimeout
On exit
D0: count (word)
Note: The _GetTimeout macro is actually not a trap, but expands to invoke the trap macro _InternalWait with a routine selector of 0 pushed on the stack.
GetTimeout returns in count the number of seconds the system will wait for the internal hard disk to respond. A value of 0 indicates the default timeout of 15 seconds.
\ SetTimeout
48
Procedure SetTimeout (count: INTEGER);
Trap macro _SetTimeout
On entry
D0: count (word)
Note: The _SetTimeout macro is actually not a trap, but expands to invoke the trap macro _InternalWait with a routine selector of 1 pushed on the stack.
SetTimeout lets you specify in count the number of seconds the system should wait for the internal hard disk to respond. The maximum value is 31 seconds; a value of 0 indicates the default timeout of 15 seconds.
\ DTInstall
49
Function DTInstall (dtTaskPtr: QElemPtr) : OSErr;
Trap macro _DTInstall
On entry
A0: dtTaskPtr (pointer)
On exit
D0: result code (word)
Note: To reduce overhead at interrupt time, instead of executing the _DTInstall trap you can load the jump vector jDTInstall into an address register other than A0 and execute a JSR instruction using that register.
DTInstall adds the specified task to the deferred task queue. Your application must fill in all fields of the task except qLink. DTInstall returns one of the result codes listed below.
Result codes
noErr No error
vTypErr Invalid queue element
\ KeyTrans
4
Function KeyTrans (transData: Ptr; keycode: Integer; VAR state: LONGINT) : LONGINT;
TransData points to a 'KCHR' resource, which maps virtual key codes to ASCII values. The keycode parameter is a 16-bit value with the structure shown in Figure 6.
The state parameter is a value maintained by the Toolbox. Your application should save it between calls to KeyTrans. If your application changes transData to point to a different 'KCHR' resource, it should reset the state value to 0.
KeyTrans returns a 32-bit value with the structure shown in Figure 7. In this structure, ASCII 1 is the ASCII value of the first character generated by the key code parameter; reserved1 is an extension for future “16-bit ASCII” coding. ASCII 2 and reserved2 have the same meanings for a possible second character generated by key code—for example, if key code designates an alphabetic character with a separate accent character.
Assembly-language note: The macro you invoke to call KeyTrans from assembly language is named _KeyTrans. Its parameters are passed on the stack.
\ AttachVBL
24
Function AttachVBL (theSlot: INTEGER) : OSErr;
Trap macro _AttachVBL
On entry
D0: theSlot (word)
On exit
D0: result code (word)
AttachVBL makes theSlot the primary video slot, allowing correct cursor updating.
Result codes
noErr No error
slotNumErr Invalid slot number
\ SlotVInstall
24
Function SlotVInstall (vblTaskPtr: QElemPtr; theSlot:INTEGER) : OSErr;
Trap macro _SlotVInstall
On entry
A0: vblTaskPtr (pointer)
D0: theSlot (word)
On exit
D0: result code (word)
SlotVInstall is identical in function to the VInstall function except that it installs the task in the queue for the device specified by theSlot.
Result codes
noErr No error
vTypErr Invalid queue element
slotNumErr Invalid slot number
\ SlotVRemove
24
Function SlotVRemove (vblTaskPtr: QElemPtr; theSlot: INTEGER) : OSErr;
Trap macro _SlotVRemove
On entry
A0: vblTaskPtr (pointer)
D0: theSlot (word)
On exit
D0: result code (word)
SlotVRemove is identical in function to the VRemove function except that it removes the task from the queue for the slot specified by theSlot.
Result codes
noErr No error
vTypErr Invalid queue element
slotNumErr Invalid slot number
\ DoVBLTask
24
Function DoVBLTask (theSlot: INTEGER) : OSErr;
Trap macro _DoVBLTask
On entry
D0: theSlot (word)
On exit
D0: result code (word)
Note: To reduce overhead at interrupt time, instead of executing the _DoVBLTask trap you can load the jump vector jDoVBLTask into an address register and execute a JSR instruction using that register.
DoVBLTask causes any VBL tasks in the queue for the specified slot to be executed. If the specified slot is the primary video slot, the position of the cursor will also be updated.
Result codes
noErr No error
slotNumErr Invalid slot number
\ ADBReInit
31
Procedure ADBReInit;
ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table to zeros and places a SendReset command on the bus to reset all devices to their original addresses. ADBReInit has no parameters.
ADBReInit is intended to be used only by installer programs that permit a new device to be connected to the ADB while the system is running. Because it does not deallocate ADB resources on the system heap, ADBReInit should not be used for routine bus initialization.
ADBReInit also calls a routine pointed to by the low memory global JADBProc at the beginning and end of its execution. You can insert your own preprocessing/ postprocessing routine by changing the value of JADBProc; ADBReInit conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing. Your procedure must restore the value of D0 and branch to the original value of JADBProc on exit. The complete ADBReInit sequence is therefore the following:
The completion routine pointed to by compRout will be passed the following parameters on entry:
D0: commandNum (byte)
A0: pointer to data stored as a Pascal string (maximum
8 bytes data preceded by one length byte)
A1: pointer to completion routine
A2: pointer to optional data area
ADBOp transmits over the bus the command byte whose value is given by commandNum. The structure of the command byte is given earlier in Figure 1. ADBOp executes only when the ADB is otherwise idle; otherwise it is held in a command queue. It returns an error if the command queue is full. The length of the data buffer pointed to by buffer is contained in its first byte, like a Pascal string. The optional data area pointed to by data is for local storage by the completion routine pointed to by compRout.
Result codes
noErr No error
–1 Unsuccessful completion
\ CountADBs
31
Function CountADBs: INTEGER;
On exit:
D0: number of devices (byte)
CountADBs returns a value representing the number of devices connected to the ADB by counting the number of entries in the device table. It has no arguments and returns no error codes.
\ GetIndADB
31
Function GetIndADB (VAR info: ADBDataBlock; devTableIndex: INTEGER) : ADBAddress;
On entry:
A0: pointer to parameter block
D0: entry index number; range = 1..CountADBs (byte)
Parameter block
• 0 device type byte
• 1 original ADB address byte
• 2 service routine address pointer
• 6 data area address pointer
On exit:
D0: positive value: current ADB address (byte)
negative value: error code (byte)
GetIndADB returns information from the ADB device table entry whose index number is given by devTableIndex. ADBDataBlock has this form:
TYPE ADBDataBlock = PACKED RECORD
devType: SignedByte; {device type}
origADBAddr: SignedByte; {original ADB address}
dbServiceRtPtr: Ptr; {service routine address}
dbDataAreaAddr: Ptr {data area address}
END;
GetIndADB returns the current ADB address of the device. If it is unable to complete execution successfully, GetIndADB returns a negative value.
\ GetADBInfo
31
Function GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
On entry:
A0: pointer to parameter block
D0: ADB address of the device (byte)
Parameter block
• 0 device handler ID byte
• 1 original ADB address byte
• 2 service routine address pointer
• 6 data area address pointer
On exit:
D0: result code (byte)
GetADBInfo returns information from the ADB device table entry of the device whose ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under “GetIndADB”.
\ SetADBInfo
31
Function SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
On entry:
A0: pointer to parameter block
D0: ADB address of the device (byte)
Parameter block
• 0 service routine address pointer
• 4 data area address pointer
On exit:
D0: result code (byte)
SetADBInfo sets the service routine address and the data area address in the ADB device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock has this form:
TYPE ADBSetInfoBlock = RECORD
siServiceRtPtr: Ptr; {service routine address}
siDataAreaAddr: Ptr {data area address}
END;
Warning: You should send a Flush command to the device after calling it with SetADBInfo, to prevent it sending old data to the new data area address.
\ OpenSlot
19
Function OpenSlot(paramBlock: paramBlkPtr; aSync: BOOLEAN) : OsErr;
If the slot sResource serves a single device (for example, a video device), clear all the bits of the ioFlags field and use the following parameter block:
Parameter block
——> 12 ioCompletion pointer
<-- 16 ioResult word
——> 18 ioNamePtr pointer
<-- 22 ioRefNum word
——> 27 ioPermssn byte
——> 28 ioMix pointer
——> 32 ioFlags word
——> 34 ioSlot byte
——> 35 ioId byte
In the extension fields, ioMix is a pointer reserved for use by the driver open routine. The ioSlot parameter contains the slot number of the device being opened, in the range 9..$E; if a built-in device is being opened, ioSlot must be 0. The ioId parameter contains the sResource ID. Slot numbers and sResources are discussed in the Slot Manager chapter of this volume.
If the slot sResource serves more than one device (for example, a chain of disk drives), set the fMulti bit in the ioFlags field (clearing all other flags bits to 0) and use the following parameter block:
Parameter block
——> 12 ioCompletion pointer
<-- 16 ioResult word
——> 18 ioNamePtr pointer
<-- 22 ioRefNum word
——> 27 ioPermssn byte
——> 28 ioMix pointer
——> 32 ioFlags word
——> 34 ioSEBlkPtr pointer
\ SIntInstall
19
Function SIntInstall(sIntQElemPtr: SQElemPtr; theSlot: INTEGER) : OsErr;
Trap macro _SIntInstall
On entry D0: slot number (word)
A0: address of slot queue element
On exit D0: error code
SIntInstall adds a new element (pointed to by sIntQElemPtr) to the interrupt queue for the slot whose number is given in theSlot. As explained in the Slot Manager chapter of this volume, slots are numbered from 9 to $E.
Assembly-language note: From assembly language, this routine has the following calling sequence (assuming A0 points to a slot queue element):
LEA PollRoutine,A1 ;get routine address
MOVE.L A1,SQAddr(A0) ;set address
MOVE.W Prio,SQPrio(A0) ;set priority
MOVE.L A1Parm, SQParm(A0) ;save A1 parameter
MOVE.W Slot,D0 ;set slot number
_SIntInstall ;do installation
This code causes the routine at label PollRoutine to be called as a result of an interrupt from the specified slot (9..$E). The Device Manager will poll the slot which has the highest priority first if two or more slots request an interrupt simultaneously.
\ SIntRemove
19
Function SIntRemove(sIntQElemPtr: SQElemPtr; theSlot: INTEGER) : OsErr;
Trap macro _SIntRemove
On entry D0: slot number (word)
A0: address of slot queue element
On exit D0: error code
SIntRemove removes an element (pointed to by sIntQElemPtr) from the interrupt queue for the slot whose number is given in theSlot. As explained in the Slot Manager chapter of this volume, slots are numbered from 9 to $E.
Assembly-language note: From assembly language, this routine has the following calling sequence (assuming A0 points to a slot queue element):
LEA MySQEl,A0 ;pointer to queue element
_SIntRemove ;remove it
This routine lets you remove an interrupt handler from the system without causing a crash.
Your driver polling routine will be called with the following assembly-language code:
MOVE.L A1Parm,A1 ;load A1 Parameter
JSR PollRoutine ;call polling routine
Your polling routine should preserve the contents of all registers except A1 and D0. It should return to the Device Manager with an RTS instruction. D0 should be set to zero to indicate that the polling routine did not service the interrupt, or nonzero to indicate the interrupt has been serviced. The polling routine should not set the processor priority below 2, and should return with the processor priority equal to 2. The Device Manager resets the VIA2 int flag and executes an RTE to the interrrupted task when a polling routine indicates that the interrupt is satisfied; otherwise, it calls the next lower-priority polling routine for that slot. If none exists, a system error results.
\ SetChooserAlert
19
Function SetChooserAlert (f:BOOLEAN) : BOOLEAN;
If f is true, the Chooser will put up the page setup alert; if f is false it won’t. SetChooserAlert returns the original alert state. The application should restore the original alert state when it exits.
Assembly-language note: If the psAlert bit of the low-memory global HiliteMode is 0 then no page setup alert will be generated. Applications that set or clear this bit must be sure not to affect any other bits in the byte and to restore the bit as they leave.
HiliteMode equ $938
psAlert equ 6
bclr #psAlert,HiliteMode
bset #psAlert,HiliteMode
\ SndPlay
47
Function SndPlay (chan: SndChannelPtr; sndHdl: Handle; async: BOOLEAN): OSErr;
SndPlay plays the 'snd ' resource specified by sndHdl. If the resource specifies a synthesizer and any modifiers to be used, the appropriate 'snth' resources are loaded and linked to the channel. The commands in the 'snd ' resource are then passed to the channel.
If chan is NIL and no modifiers are specified in the 'snd ' resource, SndPlay allocates a channel defaulting to the note synthesizer. This channel is released after the commands in the resource have been processed (in other words, after the sounds have been played).
If you specify a channel in chan, you can call SndPlay asynchronously by passing TRUE in async. If chan is NIL, you must pass FALSE in async.
SndNewChannel opens a new channel. If you pass NIL for the chan parameter, the Sound Manager opens a channel for you and returns a pointer to it.
Advanced programmers: If you’re particularly concerned with memory management, you may want to allocate a SndChannel record yourself and pass a pointer to it in chan; for details on doing this, see “Sound Manager Data Structures” below.
Synth indicates the synthesizer to be used; the following standard values have been defined:
CONST
noteSynth = 1; {note synthesizer}
waveTableSynth = 3; {wave table synthesizer}
sampledSynth = 5; {sampled sound synthesizer}
MIDISynthIn = 7; {MIDI synthesizer in}
MIDISynthOut = 9; {MIDI synthesizer out}
If you pass 0 for synth, no synthesizer is linked to the channel; you’d do this only if you intended to process commands using modifiers alone.
The init parameter is sent to the synthesizer as the second parameter of the initCmd command; its possible values are given in the description of initCmd below. The init parameter lets you request a channel with certain characteristics; this is only a request. To determine whether the requested characteristics were available, you can send the availableCmd command (described below) using the SndControl function.
If you want to supply a “call-back” routine, pass a pointer to it in userRoutine; if you pass NIL, callBackCmd commands are ignored (see “User Routines” below for a discussion of the call back routine).
SndAddModifier lets you add a modifier to an open channel. Chan contains a pointer to the channel. SndAddModifier always adds the modifier in front of the synthesizer, and in front of any modifiers previously installed.
If you want to load a 'snth' resource and add it as a modifier, pass NIL in the modifier parameter and pass the resource ID in id. The Sound Manager will load the resource, lock it, and link it to the channel.
Note: The Sound Manager saves the state of the pointer (with HGetState) and restores it when SndDisposeChannel is called (using HSetState).
If you want to add your own procedure as a modifier (instead of using an 'snth' resource), simply pass a pointer to it in the modifier parameter. The format of a modifier procedure is given in “User Routines” below.
Warning: Having too many modifiers per channel may degrade performance.
Result codes
noErr No error
resProblem Problem loading resource
badChannel Invalid channel queue length
\ SndDoCommand
47
Function SndDoCommand (chan: SndChannelPtr; cmd: SndCommand; noWait: BOOLEAN) : OSErr;
SndDoCommand inserts the given command at the end of the channel. If you specify FALSE for the noWait parameter and the queue is full, SndDoCommand waits for room in the queue. If you pass TRUE and the queue is full, SndDoCommand will not insert the command, and the result code queueFull will be returned.
Result codes
noErr No error
queueFull No room in the queue
badChannel Invalid channel queue length
\ SndDoImmediate
47
Function SndDoImmediate (chan: SndChannelPtr; cmd: SndCommand) : OSErr;
SndDoImmediate bypasses the queue and passes the given command directly to the modifiers and synthesizer.
Note: SndDoImmediate passes the command on even if the channel is waiting in response to a waitCmd or syncCmd command (described below).
Result codes
noErr No error
badChannel Invalid channel queue length
\ SndControl
47
Function SndControl (id: INTEGER; VAR cmd: SndCommand) : OSErr;
SndControl sends the given command directly to the modifier or synthesizer whose resource ID is in id. The result, if any, is returned in cmd. (Currently, only the availableCmd command is sent with SndControl; it’s described below.)
Result codes noErr No error
badChannel Invalid channel queue length
\ SndDisposeChannel
47
Function SndDisposeChannel (chan: SndChannelPtr; quitNow: BOOLEAN) : OSErr;
SndDisposeChannel closes a channel, releasing all data structures associated with it, as well as any 'snth' resources held by it. (Remember that if you allocated the SndChannel record yourself, the Sound Manager will simply restore the pointer to its original state with a call to HSetState.)
If you specify FALSE for quitNow, SndDispose channel simply places a quietCmd in the queue; commands already in the queue are processed. If you specify TRUE for quitNow, a flushCmd is passed, flushing all commands from the queue, and then a quietCmd is placed in the queue.
Your program shouldn't change the speaker volume unless
it's a Control Panel-like desk accessory, since it's
really up to the user to choose the desired volume level
via the Control Panel.
\ General Information
50
Interface Information for HyperCard 2.0 XCMDS
HyperCard 2.0: The Extended XCMD Interface 4 October 1990
External Windows: How They Work
External windows are an extension of external commands (XCMDs and XFCNs). Two new callbacks, NewXWindow and GetNewXWindow, cause HyperCard to create a new window and save with it a reference to the XCMD that made the call. Then, whenever HyperCard receives an event from the Toolbox Event Manager which belongs to the window, it calls the XCMD that created the window with arguments that allow it to handle the event. Otherwise, HyperCard handles the event itself.
Whenever an XCMD is called by HyperCard, it receives a pointer to an XCMDBlock, just as it did in earlier versions of HyperCard.
XCmdPtr = ^XCmdBlock;
XCmdBlock = RECORD
paramCount: INTEGER;
params: ARRAY[1..16] OF Handle;
returnValue: Handle;
passFlag: BOOLEAN;
entryPoint: ProcPtr; { to call back to HyperCard }
request: INTEGER;
result: INTEGER;
inArgs: ARRAY[1..8] OF LongInt;
outArgs: ARRAY[1..4] OF LongInt;
END;
When HyperCard calls an XCMD to handle an event for an external window, some of the fields of the XCMDBlock have a new meaning. The paramCount field is set to -1, indicating that the XCMD has been called to handle an event. The first parameter, params[1], is a pointer to an XWEventInfo block, defined as follows.
XWEventInfoPtr = ^XWEventInfo;
XWEventInfo = RECORD
event: EventRecord;
eventWindow: WindowPtr;
eventParams: ARRAY[1..9] OF LongInt;
eventResult: Handle;
END;
Therefore, an XCMD that manages an external window can be structured as follows:
IF paramPtr^.paramCount >= 0 THEN CreateMyWindow
ELSE
BEGIN
WITH XWEventInfoPtr(paramPtr^.params[1])^ DO
BEGIN
myEvent := event;
myWindow := eventWindow;
END;
SetPort(myWindow);
CASE myEvent.what OF
mouseDown: DoMouse;
etc...
END;
END;
When an external window is called to handle an event, it has full access to HyperTalk callback routines, just as it does when invoked from a HyperTalk script.
Events
HyperCard will automatically send most standard Macintosh events to XCMDs that manage external windows. These include:
nullEvent {see SetXWIdleTime}
mouseDown
updateEvt
activateEvt
app4Evt {floaters should hide themselves when suspended and
show themselves when resumed}
Keyboard events are sent if the XCMD is the current editing environment:
keyDown {sent if BeginXWEdit has been called}
autoKey {sent if BeginXWEdit has been called}
Keyboard events are delivered to the XCMD only if it has registered itself as the active editing environment, i.e. “has edit”, with the BeginXWEdit callback. All keystrokes, with the exception of command-key combinations recognized by the menu manager as equivalents of menu items, are sent to an XCMD when it has edit.
In addition, XCMDs will receive messages specific to HyperCard. These are delivered in the same EventRecord data structure used for standard Macintosh events, with the what field set to one of the following constants:
xOpenEvt = 1000; { the first event after you are created }
xCloseEvt = 1001; { your window is being forced close (Quit?) }
xHidePalettesEvt = 1004; { someone called HideHCPalettes }
xShowPalettesEvt = 1005; { someone called ShowHCPalettes }
xEditUndo = 1100; { Edit——Undo }
xEditCut = 1102; { Edit——Cut }
xEditCopy = 1103; { Edit——Copy }
xEditPaste = 1104; { Edit——Paste }
xEditClear = 1105; { Edit——Clear }
xSendEvt = 1200; { script has sent you a message (text) }
xSetPropEvt = 1201; { set a window property }
xGetPropEvt = 1202; { get a window property }
xCursorWithin = 1300; { cursor is within the window }
xMenuEvt = 1400; { user has selected an item in your menu }
xMBarClickedEvt = 1401; { a menu is about to be shown--update if needed }
xShowWatchInfoEvt = 1501; { for variable and message watchers }
xScriptErrorEvt = 1502; { place the insertion point }
xDebugErrorEvt = 1503; { user clicked “Debug” at a complaint }
xDebugStepEvt = 1504; { hilite the line }
xDebugTraceEvt = 1505; { same as step but tracing }
xDebugFinishedEvt = 1506; { script ended }
Handling Events
Many of the events above require special attention. Many are specific to the debugger, or other debugging tools. Here is a summary of all the events and their appropriate behavior:
nullEvent
If an external window requires idle time and registers itself as such using the SetXWIdleTime callback, it is called periodically with a nullEvent.
mouseDown, updateEvt, app4Evt
These events are dispatched in the same manner as the Toolbox Event Manager.
activateEvt
For external windows in the document layer (the same layer as the card window), activate/deactivate events are dispatched in the same manner as the Toolbox Event Manager. However, external windows in the floating layer never receive activate or deactivate events. Windows in the floating layer should always appear “active”. If your external window requires more modality, then place it in the document layer.
keyDown, autoKey
If an external window has become the active editing window by calling BeginXWEdit, it receives all keystrokes as standard Macintosh events.
xOpenEvt
After the XCMD which created the external windows completes execution, HyperTalk sends an xOpenEvt to the new external window. This is always the first event an external window receives.
xCloseEvt
HyperTalk sends your external window an xCloseEvt when your window has called CloseXWindow, when another external window or XCMD has called CloseXWindow using your window’s WindowPtr, or when the user has used the new close window “windowName” command. The external window should not dispose of any of its data until receiving this event. If the external window sets passFlag to TRUE, the window is disposed. If not, the window is left open. Refer to the discussion of the CloseXWindow callback for more information.
xGiveUpEditEvt
When an external window calls BeginXWEdit, it will receive keystrokes and edit menu commands until the user clicks back in the card window, or activates some other editing window (eg: the Message Box). HyperTalk signals the current editor with an xGiveUpEditEvt just before it activates the other editor.
xGiveUpSoundEvt
In the event that one external window requests the sound channel (with BeginXSound) while another external window has the channel, the current owner is given an xGiveUpSoundEvt. If the external window doesn’t set passFlag to true, the other external window’s callback returns with the result code set to xresFail. If an XCMD owns the sound channel, it can’t be notified of the second request, so that request will fail. The only exception to this is the HyperCard patch to _SysBeep; if an XCMD or external window owns the sound channel and someone calls SysBeep, HyperCard flashes the menubar rather than calling the XCMD.
xHidePalettesEvt
If another external window uses the HideHCPalettes callback, all external windows in the floating layer receive an xHidePalettesEvt. An example of this is the built-in Script Editor; it calls HideHCPalettes when the user edits a script.
xShowPalettesEvt
If another external window uses the ShowHCPalettes callback, all external windows in the floating layer receive an xShowPalettesEvt.
While an external window has edit, it receives these events to correspond to the items in HyperCard’s built-in Edit menu.
xSendEvt
When a user issues the send “message” to window “windowName” command, or when an XCMD or external window issues the SendWindowMessage callback, the external command receives an xSendEvt. When this event is received, eventParams[1] contains a pointer to a Pascal string (Str255) containing the name of the message. This is done for speed purposes and to expedite using the StringEqual callback to index through the commands your window supports.
xSetPropEvt,xGetPropEvt
HyperTalk contains new extensible syntax for getting and setting properties of external windows. The syntax is:
get “property” of window “windowName”
set “property” of window “windowName” to “propertyValue”
HyperTalk has two built-in properties of external windows: loc and visible. If an external window doesn’t do anything special in response to being moved or shown/hidden, it can set passFlag to TRUE in response to both xSetPropEvt and xGetPropEvt and HyperTalk will handle the request. If a property is requested other than the two built-in ones and the external window passes the event, HyperTalk will complain to the user.
If the external window wishes to respond specially to these requests, or if it has additional properties it wants to support, it can directly handle all of HyperTalk’s requests. In both xSetPropEvt and xGetPropEvt, eventParams[1] contains a pointer to a Pascal string (Str255) containing the name of the property. In the case of a xSetPropEvt, eventParams[2] contains a handle to the propertyValue. In the case of an xGetPropEvt, the external window must return a handle in the eventResult field with the value of the property requested.
HyperTalk uses property gets and sets to translate the hide and show commands. In the event the user says hide window “Variable Watcher”, HyperTalk informs the external window by giving it an xSetPropEvt with the property “visible” and the value “false”.
For an example of the ability of external windows to use properties, try these properties of the Message Watcher window: loc, visible, hideIdle, hideUnused, text, and lastLine (set only). The Variable Watcher supports the following properties: loc, visible, hBarLoc, vBarLoc, and rect.
For the convenience of all concerned, there are four new callbacks to aid in getting and setting properties: PointToStr, RectToStr, StrToPoint, and StrToRect.
xCursorWithin
This event is sent when the cursor is over any part of the external window. If the external window sets passFlag to TRUE, HyperCard sets the cursor to an arrow.
xMenuEvt
When an external window has used RegisterXWMenu for one or more menus in HyperCard’s menubar, HyperTalk notifies it of an item being chosen by sending it an xMenuEvt. This holds true for command-key equivalents as well. When the event is received, eventParams[1] is the menu ID and eventParams[2] is the menu item.
xMBarClickedEvt
If an external window has registered one or more menus in the menubar, HyperTalk sends it an xMBarClickedEvt just before it calls the Menu Manager’s MenuSelect or MenuKey routines. This is to allow the external window to adjust its menus just before the user sees them.
xShowWatchInfoEvt
Sent to the Message Watcher and Variable Watcher whenever it is appropriate. The message watcher gets eventParams[1] set to a handle to the current message, indented with 2 space characters for each level of nesting. The variable watcher gets no arguments.
[.... ** detailed info on script editor events is omitted for my convinience...KK]
Window layer management
Within HyperCard, each window resides in one of two layers, the floating layer or the document layer.
The floating layer is reserved for windows that have a single state, such as HyperCard’s tool window, which is always active when it is visible. All of HyperCard’s floating windows, including the message box and the tool window, reside in this layer. Every visible window in the floating layer is active at all times. Windows in this layer never receive activate and deactivate events.
The rear layer is the document layer. Windows that have multiple states, active and inactive, such as HyperCard’s card windows and script editing windows, reside in this layer. Only one window in this layer is active at a time.
XCMDs determine the layer in which their external windows reside using the floating argument to GetNewXWindow and NewXWindow. If floating is TRUE, the window is placed at the front of the floating layer, otherwise it is placed at the front of the document layer.
FUNCTION NewXWindow(paramPtr: XCmdPtr; boundsRect: Rect; title: Str255; visible: BOOLEAN;
FUNCTION GetNewXWindow(paramPtr: XCmdPtr; templateType: ResType; templateID: INTEGER;
color: BOOLEAN; floating: BOOLEAN): WindowPtr;
An XCMD can check the frontmost window of the floating layer using the Window Manager’s FrontWindow function. An XCMD can use the FrontDocWindow XCMD callback find the frontmost window in the document layer.
Memory Management Tips
HyperCard 2.0 contains tremendous amounts of new functionality, and one of its new features was implemented in a way that may conflict with a generally-accepted XCMD and Macintosh Toolbox programming convention.
The Macintosh Memory Manager will allocate two different types of heap blocks: relocatable and non-relocatable. Nonrelocatable blocks (“pointers”) are allocated as low as possible in the heap, and relocatable blocks (“handles”) are allocated wherever possible. A problem will arise if an XCMD or external window leaves a non-relocatable block (or a locked relocatable block) allocated after it returns control to HyperCard, and the user attempts to go to a stack that is larger than classic size (512 pixels wide and 342 pixels high). This condition is commonly called an island in the heap. Even though HyperTalk’s heapSpace function may indicate lots of free memory, the user will be limited to classic card size, scrolling will be slower, and they will be prevented from using the Painting tools.
Follow the simple rules below and life will be far richer for your XCMD and external window users:
1) Nonrelocatable blocks are OK to use temporarily, but do not leave them allocated when the XCMD returns control to HyperCard.
2) Locked relocatable blocks are also OK to use, but try to lock the block only when it is actually being accessed, then either dispose it or unlock it.
3) If an XCMD requires a block to be locked permanently, it should call NewHandle, and if that call is successful, it should call MoveHHi before it calls HLock. Some more complex XCMDs may contain code meant to run at interrupt level or code (such as ROM patches) to which absolute addresses must be calculated. Once a relocatable block is locked, that block is just as immovable as a nonrelocatable block, but much nicer from the HyperCard user’s perspective.
4) Also, be careful with callbacks such as SendCardMessage while blocks are locked in the heap, because these callbacks can cause HyperCard to change stacks if the message issues a go command.
\ EvalExpr
51
FUNCTION EvalExpr(paramPtr: XCmdPtr; expr: Str255): Handle;
EvalExpr evaluates the HyperTalk expression passed in expr and returns a handle to a zero-terminated string containing the result of the evaluation. For example, EvalExpr('the long date') returns a handle to a string containing the current date in the long format (Saturday, June 25, 1988). The caller must dispose of the handle. If the callback fails to evaluate properly because of an error, EvalExpr returns NIL and paramPtr^.result is set to xresFail.
RunHandler is similar to the HyperTalk do command. The zero-terminated string in handler is interpreted first as a message. If it is a message (command or function), it is sent to the current card. If it is one line of HyperTalk, it is executed as though it were in the message box. The text can contain multiple lines of HyperTalk, including conditional statements and repeat loops. If it is multiple lines of HyperTalk, the lines are also executed as though from the message box. If it is multiple lines beginning with on <messageName> and ending with end <messageName>, messageName is “sent” to this handler in the context of the card. If the handler exits, execution terminates. If the handler contains the line pass <messageName>, the messageName is passed up HyperTalk’s normal inheritance chain, beginning with the current card script.
Note: You can not override a script executed with RunHandler. In other words, if the current card has an on doSomething handler, and an XCMD issues a RunHandler callback with an on doSomething, the XCMD’s handler will be executed. If the handler passes the message, the card’s script will be executed.
Another note: Execution is somewhat slower using RunHandler than it would be running the same script as a card handler. You also can not use the debugging tools to debug these scripts.
A Word About HyperTalk Errors: In normal HyperTalk script execution, an alert is displayed when a script encounters an error. For example, entering the long tade (“date” is misspelled) in the message box will display a “Can’t understand…” message. This alert is called a complaint. When HyperTalk displays a complaint, it terminates all pending handlers and returns to idle. This is the same behavior that takes place when a user types Command-Period while running a script. Since HyperCard 1.2, HyperTalk doesn’t display a complaint when a script error is encountered by an XCMD callbacks. This holds true not only for messages themselves, but any handlers called by those messages.
If a callback encounters a script error, execution of the callback stops and control is returned to the XCMD. Whenever an XCMD makes a HyperTalk callback, it should check paramPtr^.result. If result is not xresSucc, then the callback failed. Depending on the situation, the XCMD might elect to display an appropriate error message and terminate execution. For example, the assumption that EvalExpr always returns a valid handle is dangerous, because in the event that it fails, EvalExpr returns NIL. Trying to manipulate a NIL handle can result in a System Error (bomb).
\ GetGlobal
51
FUNCTION GetGlobal(paramPtr: XCmdPtr; globName: Str255): Handle;
GetGlobal returns a handle to a zero-terminated string that contains a copy of the contents of the HyperTalk global variable globName. If globName doesn’t exist, GetGlobal returns a handle to an empty string. The caller must dispose of the handle.
SetGlobal copies the zero-terminated string to which globValue is a handle into the HyperTalk global variable named globName. If globName doesn’t exist, SetGlobal creates it. HyperCard does not dispose of globValue.
ZeroBytes sets longCount bytes beginning at dstPtr to 0. It performs no boundary checking. For example, it can write past the end of a zero-terminated string.
\ ScanToRetrun
51
PROCEDURE ScanToReturn(paramPtr: XCmdPtr; VAR scanPtr: Ptr);
ScanToReturn scans along the zero-terminated string pointed to by scanPtr, stopping just past the first return character or at the end of the string. scanPtr is incremented to point to the new location.
\ ScanToZero
51
PROCEDURE ScanToZero(paramPtr: XCmdPtr; VAR scanPtr: Ptr);
ScanToZero scans along the zero-terminated string pointed to by scanPtr, stopping at the end of the string. scanPtr is incremented to point to the new location.
\ StringEqual
51
FUNCTION StringEqual(paramPtr: XCmdPtr; str1,str2: Str255): BOOLEAN;
StringEqual compares the two Pascal strings str1 and str2 (case-insensitive and diacritical-sensitive) and returns TRUE if the two strings are identical; otherwise it returns FALSE.
\ StringLength
51
FUNCTION StringLength(paramPtr: XCmdPtr; strPtr: Ptr): LongInt;
StringLength returns the number of characters in the zero-terminated string pointed to by strPtr. Note that strPtr is a pointer, not a handle.
\ StringMatch
51
FUNCTION StringMatch(paramPtr: XCmdPtr; pattern: Str255; target: Ptr): Ptr;
StringMatch performs a case-insensitive search for pattern (a Pascal string) in the zero-terminated string pointed to by target. If the search is successful, the location of the first matching character is returned as the function result. If the search is unsuccessful, StringMatch returns nil. This is equivalent to HyperTalk’s offset function.
ZeroTermHandle grows the block referenced by hndl by one byte and then sets the extra byte to 0, making hndl legal for operations such as SetGlobal and ZeroToPas.
\ BoolToStr
51
PROCEDURE BoolToStr(paramPtr: XCmdPtr; bool: BOOLEAN; VAR str: Str255);
BoolToStr converts bool to a Pascal string (“true” or “false”).
\ ExtToStr
51
PROCEDURE ExtToStr(paramPtr: XCmdPtr; num: Extended; VAR str: Str255);
ExtToStr converts num (a SANE extended type) to a Pascal string.
\ LongToStr
51
PROCEDURE LongToStr(paramPtr: XCmdPtr; posNum: LongInt; VAR str: Str255);
LongToStr converts posNum (a 32-bit unsigned integer) to a Pascal string.
\ NumToHex
51
PROCEDURE NumToHex(paramPtr: XCmdPtr; num: LongInt; nDigits: INTEGER; VAR str: Str255);
NumToHex returns in str a hexidecimal (base 16) representation of the value of num, expanding the string to nDigits in length.
\ NumToStr
51
PROCEDURE NumToStr(paramPtr: XCmdPtr; num: LongInt; VAR str: Str255);
NumToStr converts num (a 32-bit signed integer) to a Pascal string.
\ PasToZero
51
FUNCTION PasToZero(paramPtr: XCmdPtr; str: Str255): Handle;
PasToZero converts str to a zero-terminated string and returns a handle to the new string. The caller must dispose of the handle.
\ ReturnToPas
51
PROCEDURE ReturnToPas(paramPtr: XCmdPtr; zeroStr: Ptr; VAR pasStr: Str255);
ReturnToPas copies characters from the zero-terminated string pointed to by zeroStr into the Pascal string pasStr, stopping at the first return character (ASCII $0D), the end of the zero-terminated string, or the 255th character, whichever comes first.
\ StrToBool
51
FUNCTION StrToBool(paramPtr: XCmdPtr; str: Str31): BOOLEAN;
StrToBool converts str to a boolean (TRUE or FALSE) and returns the boolean value as its result.
\ StrToExt
51
FUNCTION StrToExt(paramPtr: XCmdPtr; str: Str31): Extended;
StrToExt converts str to an extended type. Extended numbers contain a sign bit, 15 bits for the exponent and 63 bits for the significand. This is the standard data type for SANE, the Standard Apple Numeric Environment.
\ StrToLong
51
FUNCTION StrToLong(paramPtr: XCmdPtr; str: Str31): LongInt;
StrToLong converts str to a long (32-bit) unsigned integer. Unsigned long integers range from 0 to 4,294,967,296.
\ StrToNum
51
FUNCTION StrToNum(paramPtr: XCmdPtr; str: Str31): LongInt;
StrToNum converts str to a long (32-bit) signed integer. Signed long integers range from (-2,147,483,648) to 2,147,483,648.
\ ZeroToPas
51
PROCEDURE ZeroToPas(paramPtr: XCmdPtr; zeroStr: Ptr; VAR pasStr: Str255);
ZeroToPas converts the zero-terminated string pointed to by zeroStr to a Pascal string and returns the string in pasStr.
\ PointToStr
51
PROCEDURE PointToStr(paramPtr: XCmdPtr; pt: Point; VAR pasStr: Str255);
PointToStr converts the point passed in pt to a Pascal string and returns the string in pasStr.
\ RecToStr
51
PROCEDURE RectToStr(paramPtr: XCmdPtr; rct: Rect; VAR pasStr: Str255);
RectToStr converts the rectangle passed in rct to a Pascal string and returns the string in pasStr.
\ StrToPoint
51
PROCEDURE StrToPoint(paramPtr: XCmdPtr; pasStr: Str255; VAR pt: Point);
StrToPoint converts the Pascal string passed in pasStr to a point and returns the point in pt.
\ StrToRect
51
PROCEDURE StrToRect(paramPtr: XCmdPtr; pasStr: Str255; VAR rct: Rect);
StrToRect converts the Pascal string passed in pasStr to a rectangle and returns the rectangle in rct.
\ GetFieldByID
51
FUNCTION GetFieldByID(paramPtr: XCmdPtr; cardFld: BOOLEAN; fldID: INTEGER): Handle;
GetFieldByID returns a handle to a zero-terminated string that contains a copy of the contents of field ID fldID. If cardFld is TRUE, fldID is a card field; otherwise it is a background field.
\ GetFieldByName
51
FUNCTION GetFieldByName(paramPtr: XCmdPtr; cardFld: BOOLEAN; fldName: Str255): Handle;
GetFieldByName returns a handle to a zero-terminated string that contains a copy of the contents of field fldName. If cardFld is TRUE, fldName is a card field; otherwise it is a background field.
\ GetFieldByNum
51
FUNCTION GetFieldByNum(paramPtr: XCmdPtr; cardFld: BOOLEAN; fldNum: INTEGER): Handle;
GetFieldByNum returns a handle to a zero-terminated string that contains a copy of the contents of field number fldNum. If cardFld is TRUE, fldNum is a card field; otherwise it is a background field.
SetFieldByID copies the zero-terminated string to which fldVal is a handle into the field ID fldID. If cardFld is TRUE, fldID is a card field; otherwise it is a background field. The caller must dispose of the handle.
SetFieldByName copies the zero-terminated string to which fldVal is a handle into field fldName. If cardFld is TRUE, fldName is a card field; otherwise it is a background field. The caller must dispose of the handle.
SetFieldByNum copies the zero-terminated string to which fldVal is a handle into the field number fldNum. If cardFld is TRUE, fldNum is a card field; otherwise it is a background field. The caller must dispose of the handle.
GetFieldTE returns a copy of the Styled TEHandle from the specified field, including style runs (see Inside Macintosh: Volume V). The caller must dispose of this TEHandle.
To determine which field the XCMD wants to manipulate, HyperTalk uses the following logic: if fieldID is non-zero, then HyperTalk uses it. If fieldNum is non-zero, then HyperTalk uses it. Finally, if fieldNamePtr is not NIL, HyperTalk uses the field name pointed to by it. If GetFieldTE returns NIL, the field was not found or there wasn’t enough memory to copy the text and styles. The caller must dispose of this TEHandle.
Note: the XCMD should not use the TEHandle returned by this callback before adjusting the TEHandle^^.inPort field to point to another grafPort. HyperTalk sets this field to point to the card window when this callback returns, so routines like TEUpdate and TESetSelect may cause the text to draw into the card window.
SetFieldTE sets the text and styles of the field to the text and styles contained in fieldTE. See GetFieldTE for a description of the use of fieldID, fieldNum, and fieldNamePtr. The caller must dispose of this TEHandle.
An XCMD should call BeginXSound before it attempts to allocate a sound channel or perform any other Sound Manager operation. After an XCMD calls BeginXSound, HyperCard’s built-in play command will not operate until the XCMD calls EndXSound (see below). If an external window is making the callback, it should pass a pointer to its window in the window parameter. An XCMD should pass NIL for the window parameter. An XCMD or an external window can optionally pass a pointer to a valid external window in the window parameter if it wants to “aim” the call at another external window. If HyperTalk gets a valid windowPtr in window, it will post an xGiveUpSoundEvt to that window at an appropriate time. If the XCMD passes NIL for window, HyperCard will be unable to signal the XCMD when HyperCard needs the sound channel back.
An XCMD that uses the Sound Manager can be structured as follows:
BeginXSound(paramPtr,NIL);
(* allocate a sound channel *)
(* make some noise *)
(* deallocate sound channel *)
\ EndXSound
51
EndXSound(paramPtr);
PROCEDURE EndXSound(paramPtr: XCmdPtr);
EndXSound informs HyperCard that an XCMD has finished using the Sound Manager. If an XCMD has not previously called BeginXSound, EndXSound does nothing.
\ GetFilePath
51
FUNCTION GetFilePath(paramPtr: XCmdPtr; fileName: Str255; numTypes: INTEGER;
typeList: SFTypeList; askUser: BOOLEAN;
VAR fileType: OSType; VAR fullName: Str255): BOOLEAN;
GetFilePath determines the full pathname of the file fileName using the search paths stored in the Home stack. If fileType is 'STAK', GetFilePath uses the stack search paths. If fileType is 'APPL', GetFilePath uses the application search paths. If fileType is neither 'STAK' nor 'APPL', GetFilePath uses the document search paths. numTypes and typeList are used as they are described in Inside Macintosh Volume I, page 523. If askUser is TRUE and HyperCard fails to find the file on its own, GetFilePath prompts the user to find the file with a Standard File dialog. If the file is located either by HyperCard or by the user, the full pathname of the file is returned in fullName and the file type is returned in fileType. If the user clicks “Cancel” in the Standard File dialog or HyperCard fails to find the file for any other reason, GetFilePath returns FALSE.
\ GetXResInfo
51
PROCEDURE GetXResInfo(paramPtr: XCmdPtr; VAR resFile: INTEGER;
VAR resID: INTEGER; VAR rType: ResType;
VAR name: Str255);
GetXResInfo returns the file reference number of the resource file from which the calling XCMD was read in resFile and the resource ID of the XCMD in resID, the resource type (XCMD or XFCN) in rType, and the resource name in name.
\ Notify
51
PROCEDURE Notify(paramPtr: XCmdPtr);
If HyperCard is active or MultiFinder is not loaded, Notify returns immediately. Otherwise, Notify blinks the small HyperCard icon over the menu until the user switches to HyperCard’s layer. Only then does Notify return. No other HyperCard processing takes place while Notify is waiting.
SendHCEvent is useful only to XCMDs that call the ToolBox routines GetNextEvent or WaitNextEvent. Such XCMDs should use SendHCEvent to “pass” events required by HyperCard. For example, an XCMD that creates a draggable window and calls GetNextEvent may receive update events for HyperCard’s windows. HyperCard will perform the updates if it receives the update events via this callback. More importantly, an XCMD that calls GetNextEvent and receives an app4Evt generated by MultiFinder must pass the event along to HyperCard. If HyperCard does not receive its suspend and resume events, bad things can happen.
XCMDs that create windows by means of the NewXWindow callback don’t need to call GetNextEvent or WaitNextEvent and therefore don’t need to use SendHCEvent.
SendWindowMessage is functionally equivalent to send <msg> to window <windowName> from HyperTalk. Use this for direct communication between XCMDs that manage external windows. If windPtr is not NIL, the window pointer is used to determine which window will receive the message, otherwise the name is used.
\ FrontDocWindow
51
FUNCTION FrontDocWindow(paramPtr: XCmdPtr): WindowPtr;
FrontDocWindow returns the WindowPtr of the document which is frontmost in HyperCard’s document layer. This will not return the WindowPtr of a window in the palette layer. To return the frontmost window of any type, use the Window Manager’s FrontWindow function.
\ StackNameToNum
51
FUNCTION StackNameToNum(paramPtr: XCmdPtr; stackName: Str255): LongInt;
Internally, HyperCard no longer only remembers stacks by their name. It uses a stack number to represent the stack. This number is akin to a volume reference number: it is valid as an indicator as long as the application is open, but won’t be valid across multiple launches. This number is valid when used in an XTalkObject to get and set the scripts of objects. StackNameToNum translates the name of a stack into this number.
\ ShowHCAlert
51
FUNCTION ShowHCAlert(paramPtr: XCmdPtr; dlgID: INTEGER;
promptStr: Str255): INTEGER;
HyperCard contains four standard alert windows. XCMDs can use these, along with all of the smart window-centering, text-expanding, and command-key handling without having to use the answer and ask commands any more. dlgID must be one of the following constants.
errorDlgID = 1; { 1:OK (default) }
confirmDlgID = 2; { 1:OK (default) and 2:Cancel }
confirmDelDlgID = 3; { 1:Cancel (default) and 2:Delete }
yesNoCancelDlgID = 4; { 1:Yes (default), 2:Cancel, and 3:No }
The values listed in the comments correspond to the function results returned by ShowHCAlert. For example:
CASE ShowHCAlert(paramPtr,yesNoCancelDlgID,'Delete file "Fred?"') OF
1: DeleteTheFile; { user chose “OK” }
2: Abort; { user chose “Cancel” }
3: Continue; { user chose “No” }
END;
The pascal string in promptStr can contain the Dialog Manager’s wildcard characters (^0, ^1, ^2, and ^3) if the XCMD calls ParamText before calling ShowHCAlert.
\ GetNewXWindow
51
FUNCTION GetNewXWindow(paramPtr: XCmdPtr; templateType: ResType;
templateID: INTEGER; color: BOOLEAN;
floating: BOOLEAN): WindowPtr;
GetNewXWindow creates a new window or dialog from a resource. If the Window Manager fails to create the window, GetNewXWindow returns NIL. If the window is created successfully, GetNewXWindow sets up the mechanism by which events pertaining to the window are sent to the XCMD that created it.
templateType must be either 'WIND' or 'DLOG'. templateID is the resource ID of the window or dialog template to be used. The template resource can exist in any resource file that’s currently open.
If colorWind is TRUE, HyperTalk attempts to create a color window using the GetNewCWindow or NewCDialog toolbox trap. If colorWind is TRUE and Color QuickDraw is not present, the window is not created and GetNewXWindow returns NIL.
Note: GetNewXWindow is compatible with non-standard window definition functions (see NewXWindow below for more information).
\ NewXWindow
51
FUNCTION NewXWindow(paramPtr: XCmdPtr; boundsRect: Rect; title: Str255;
NewXWindow creates a new window and returns a pointer to it as the function’s result. If the Window Manager fails to create the window, NewXWindow returns NIL. If the window is created successfully, NewXWindow sets up the mechanism by which events pertaining to the window are sent to the XCMD that created it.
If colorWind is TRUE, HyperTalk attempts to create a color window using the NewCWindow toolbox trap. If colorWind is TRUE and Color QuickDraw is not present, the window is not created and NewXWindow returns NIL.
procID is the same as the procID argument to the Window Manager routine NewWindow. For example, passing documentProc as the procID produces a standard document window with no zoom box. boundsRect is the bounding rectangle for the window in global coordinates. title becomes the title of the window.
The visible argument determines whether the window will be created visible.
To create windows similar to HyperCard’s palettes, such as the tool window and the message box, use HyperCard’s built-in window definition function for palettes. Here are the values to use for procID:
paletteProc = 2048; { Palette with grow box }
palNoGrowProc = 2052; { standard Palette defproc }
palZoomProc = 2056; { Palette with zoom and grow }
palZoomNoGrow = 2060; { Palette with zoom and no grow }
hasZoom = 8;
hasTallTBar = 2;
toggleHilite = 1;
For example, the Navigator palette uses palNoGrowProc for procID.
Note: NewXWindow is also compatible with other non-standard window definition functions.
When an XCMD which manages an external window requests that the window be closed, it should call CloseXWindow. When all pending calls to the XCMD have returned, HyperCard sends an xCloseEvt to the XCMD. Only in response to this event should it dispose of its data structures and exit.
When the external window receives the xCloseEvt, it signals its willingness to close by setting paramPtr^.passFlag to TRUE. If this is not done, HyperTalk will not proceed with the deallocation of the window.
Any XCMD can close any external window by means of a call to CloseXWindow. CloseXWindow has no effect on windows that were not created by means of a call to NewXWindow or GetNewXWindow.
The receipt of an xCloseEvt is the signal that it is safe to deallocate memory and perform other cleanup operations.
Warning: HyperTalk tries to close all open external windows when the user quits HyperCard. If any windows refuse to close at that time, HyperCard will not quit.
Another Warning: Do not use any of the following Toolbox routines to close external windows: CloseWindow, DisposeWindow, CloseDialog, or DisposDialog.
\HideHCPalettes
51
PROCEDURE HideHCPalettes(paramPtr: XCmdPtr);
HideHCPalettes hides all of HyperCard’s built-in palettes (the tool window, the pattern window, the fatbits window, and the message box). It also sends an xHidePalettesEvt to all windows in the floating layer.
\ ShowHCPalettes
51
PROCEDURE ShowHCPalettes(paramPtr: XCmdPtr);
ShowHCPalettes reverses the effect of HideHCPalettes, showing all of HyperCard’s palettes that were visible when HideHCPalettes was called to hide them. It also sends an xShowPalettesEvt to all windows in the floating layer.
RegisterXWMenu is useful only to XCMDs that manage external windows. RegisterXWMenu informs HyperCard that the given menu is meant for use with the external window in window. When an item in the menu is selected by the user or specified as the menu item parameter to the doMenu command, the XCMD that registered the menu will receive a menu event (xMenuEvt). Note that an XCMD can register one of HyperCard’s menus, e.g. the Font menu, in order to temporarily borrow the menu.
RegisterXWMenu does not change the menubar. The XCMD must call the Menu Manager in order to insert or delete the menu and to redraw the menubar. Once the menu has been registered, it remains the property of the XCMD until RegisterXWMenu is called again with registering set to FALSE.
Note: HyperCard expects XCMD menus to have unique IDs but does not ensure that they do. You may employ the following function to find an unused menu ID.
XCMDs that manage external windows can request idle time from HyperCard. Use SetXWIdleTime if your XCMD needs to perform a periodic action.
Call SetXWIdleTime with a value greater than 0 for ticks to set the interval between periodic calls by HyperCard. HyperCard sends the XCMD a nullEvent when making its periodic call. To give up idle time, call SetXWIdleTime with a value of 0 for ticks.
Whether HyperCard’s periodic calls occur as often as requested depends on whether HyperCard is currently performing a time-critical or data-intensive operation.
Note: nullEvents are sent in both the foreground and background under MultiFinder, and under the Paint tools as well.
When HyperCard creates an external window (by means of either the NewXWindow or GetNewXWindow callback), it is assumed that the code of the XCMD that manages it can be moved in memory while not executing.
If haveCode is TRUE, HyperCard will never unlock the relocatable block containing the XCMD code in memory. This allows ProcPtrs and other addresses within an XCMD’s code to be preserved and valid at all times. XWHasInterruptCode should be used with extreme prudence and should be undone as soon as possible— HyperCard’s memory management can become seriously taxed if there are any locked blocks inconveniently located in its heap. In particular, it’s impossible to open card windows at the full size of large cards when a nonrelocatable block is located too close to the bottom of the application heap.
The preferred method for an XCMD to manage procedure pointers passed to the Toolbox is to refresh them as needed rather than to call XWHasInterruptCode to ensure their validity. This method permits HyperCard to unlock the XCMD’s code between invocations. An example of such an XCMD is a text editor with a custom clikLoop routine. For best results, such an XCMD will recalculate and refresh its procPtr every time the user clicks in the viewRect. For example:
CASE evt.what OF
mouseDown:
BEGIN
GlobalToLocal(evt.where);
hTE^^.clikLoop := @MyClikLoop; { assembly language custom click loop }
TEClick(evt.where, FALSE, hTE);
END;
An XCMD that uses this method doesn’t need to call XWHasInterruptCode.
An XCMD’s code is always locked while it is actually executing. XWHasInterruptCode determines only whether the block of code can be unlocked when control is returned to HyperCard.
XWAlwaysMoveHigh tells HyperTalk to always move the external window’s code high on the heap before locking it down and calling it. External windows which may allocate large amounts of memory or send card messages to do such operations as go to another card should use this.
Background: In normal XCMD and external window operations, HyperTalk makes a determination at the time the code is jumped to as to whether the code should be moved high in the application heap before being locked down. Currently, this is done whenever an XCMD is called, and when an external window is given the following events: xOpenEvt, xMenuEvt, mouseDown, and keyDown. All other events are assumed to rarely cause memory allocation or messages to be sent, therefore HyperTalk can speed up the process of calling and returning from an external window. However, some external windows may elect to allocate memory on such things as an xSetPropEvt. For example, a Picture XCMD could be asked to change information about the currently-displayed PICT and that may cause memory to be allocated. A good rule of thumb is this: if your external window is not called repeatedly in a script and you might allocate memory on events other than the aforementioned events, call this with moveHigh = TRUE.
Using XWAllowReEntrancy, an XCMD can tell HyperCard whether it is equipped to receive events (either system events or HyperCard-generated events) in a reentrant fashion. Either of the booleans, allowSysEvts or allowHCEvts, can be set to true or false to enable or disable (respectively) this behavior.
In certain situations, it is possible for an external window to generate events for itself. In other words, calling the Window Manager’s InvalRect routine on a portion of the window could create an updateEvt for the window. When is this updateEvt delivered?
While running scripts, HyperTalk periodically checks the Event Manager to see if update, activate, or MultiFinder events are pending. This is how HyperCard processes events in the background. In the course of these checks, the Window Manager may report an update event for the external window if it notices that any or all of the window is invalid. The problem arises from external windows that use SendCardMessage, SendHCMessage, EvalExpr, or any other HyperTalk callback that can run a script. XWAllowReentrancy was implemented to allow external windows to have asynchronous handling of certain events. For example, if a SendCardMessage callback causes a lengthy script to be executed, the external window may want to be notified that the user switched out of HyperCard under MultiFinder. To defend against unexpected events, an XCMD can use XWAllowReEntrancy to temporarily turn of reentrancy.
Unlike system events, HyperTalk “events” are not queued, so unreceived events end up in the bit bucket.
Note: HyperTalk defaults to not allowing reentrancy.
Note: Because xGetPropEvt and xSetPropEvt are events, if an external window has not called XWAllowReEntrancy(paramPtr,xxxx,TRUE), the scenario described below will result in the external window never receiving its xSetPropEvt for its visible property:
External Window “fred”: SendCardMessage(paramPtr,’go next card’);
closeCard script: on closeCard
hide window “fred” - this call will fail
end closeCard
The xSetPropEvt will cause the external window to be reentered, so HyperTalk will skip the event and continue. If your external window needs to communicate with running scripts, make sure that you allow it to be reentrant.
Warning: If an external window notifies HyperCard that it can receive reentrant system events, it may receive an unexpected updateEvt. Many Macintosh programmers use InvalRect or InvalRgn in order to allow asynchronous window updating. In applications, this allows more operations to take place between potentially time-consuming window redraws. However, any callback that executes lines of HyperTalk (eg: SendCardMessage, EvalExpr) also polls the Event Manager for pending events. If there are no other pending events, the external window may receive a reentrant updateEvt at this time. To guard against that, use XWAllowReEntrancy to temporarily turn of reentrancy if this has a potential of happening.
Another Warning: Writing completely reentrant code is difficult, and some development systems may not support reentrancy correctly. One tip is to make sure that every time an external window receives an event, it should completely save and restore its state. A good idea is to use the external window’s refCon field to store a handle to all the window’s state information. Beware of the use of “global variables” in stand alone code resources. See Macintosh Technical Note #256 for more information.
BeginXWEdit registers an external window as the current editing environment. Once BeginXWEdit is called, HyperCard redirects all keystrokes to the XCMD, with the exception of command-key combinations recognized by the Menu Manger as the equivalent of menu items. In addition, HyperCard passes events to the XCMD that correspond to the first five items in the Edit menu whenever these items are selected. The XCMD still receives all of the other events pertaining to its window, including nullEvents if it has requested them.
Once the XCMD has registered itself as the current editing environment, it is liable to receive an xGiveUpEdit event from HyperCard when the user performs an action that activates a different editing environment, such as a click in the message box or in an unlocked field. When this happens, the XCMD should deactivate its editable area as appropriate, just as it does when its window is deactivated.
EndXWEdit informs HyperCard that an XCMD no longer wants to receive keystrokes and edit events for its external window. Call EndXWEdit before an external window that has edit is closed via a call to CloseXWindow.
\ HCWordBreakProc
51
FUNCTION HCWordBreakProc(paramPtr: XCmdPtr): ProcPtr;
HCWordBreakProc returns a procedure pointer to HyperCard’s built-in word-break routine used for text in fields, scripts, and the message box. Script Editors and other text-editing XCMDs can use this address in the wordBreak field of a TextEdit record.
Given a handle to a TextEdit record in hTE, PrintTEHandle displays a Print Job dialog and prints the record using the font, size, and style information contained within it. PrintTEHandle works for both old- and new-style edit records.